23

I was listening to this episode of JavaScript Jabber:

http://javascriptjabber.com/120-jsj-google-polymer-with-rob-dodson-and-eric-bidelman/

At one point Rob says:

And everyone has this first inclination, because it makes so much sense. You’re like, “Bootstrap is components. I’m just going to make them into tags.” But then you run into the fact that the Bootstrap style sheet is just one big long style sheet that was written assuming that it could touch every part of the document. And when you are suddenly scoping bits of the markup, scoping it so that the CSS can’t reach it, the CSS would actually have to be in the Shadow DOM with it and you would have to write that element from the ground up, that’s where people I think get really confused and really frustrated initially.

This made me wonder, how would you solve this problem with Web Components? Is there a way for Shadow DOM templates to inherit common styles, or would you have to repeat shared CSS for each separate component? Or something else?

anderspitman
  • 9,230
  • 10
  • 40
  • 61
  • 5
    This question isn't "too broad" - it has a pretty succinct answer (in a true Shadow DOM implementation anyway). – Pointy Aug 08 '14 at 20:13
  • I've post different approach to solve the problem, see the last answer. – Timur Fayzrakhmanov Apr 17 '15 at 21:25
  • Shadow DOM creates new dom trees. So it provides encapsulation. You can access the :host and/or :host-context() and ::shadow so you could have a notion of a global theme that can access the shadow DOM elements, just as you could access it in a today. Additionally other parts of the web component spec like templates and html imports would provide cleaner and more shareable components. – BingeBoy Apr 24 '15 at 03:28

5 Answers5

13

Note: the substance of the answer below is no longer relevant, as the features discussed have been deprecated for some time. Don't use the sample code, but feel free to take a peek into the Internet past.


In a complete Shadow DOM implementation, CSS has a ::shadow pseudo-class, and also the /deep/ combinator.

The ::shadow pseudo-class lets you break into the shadow DOM under an element, and it matches the shadow root. The /deep/ combinator effectively opens up the shadow DOM completely.

Thus, if you had a <x-foo> element with <span> elements inside, you could make them red with

x-foo::shadow span { color: red; }

Or make all <spans> in any shadow DOM red:

body /deep/ span { color: red; }
Pointy
  • 405,095
  • 59
  • 585
  • 614
  • 1
    I'm aware of ::shadow and /deep/, but seem far from an elegant solution. Is there anything better? – anderspitman Aug 09 '14 at 07:49
  • 5
    @anders ?? what would be *better*?? How is it any less elegant than the rest of CSS? – Pointy Aug 09 '14 at 13:42
  • 6
    `/deep/`, `::shadow` and `>>>` are deprecated and will be removed eventually. – Günter Zöchbauer Mar 07 '16 at 09:18
  • @GünterZöchbauer that's interesting; the [31 Jan 2016 draft](https://drafts.csswg.org/css-scoping/#shadow-dom) of the Scoping Module still includes `::shadow` and `>>>` though they're marked with "issues". – Pointy Mar 07 '16 at 14:46
  • 1
    Interesting. The discussion in the Chrome issue was not about whether to remove or not but just how long to keep it deprecated before removing. The Polymer team is moving away from using them everywhere as well. I think this is settled. – Günter Zöchbauer Mar 07 '16 at 14:55
  • You should remove this answer, because both ::shadow and /deep/ have been deprecated since 2013 and people won't read the comments, but still copy the code. – Rudie Mar 28 '17 at 14:08
  • @Rudie well, there's lots of dreck around this place :) I will definitely update the answer however. – Pointy Mar 28 '17 at 19:02
7

The current state of the Shadow DOM / CSS is that you can link to external stylesheets. More info at MDN: https://developer.mozilla.org/en-US/docs/Web/Web_Components/Using_shadow_DOM#Internal_versus_external_styles

You could, then, have some sort of utility stylesheet (Tailwind or similar) that all of your components reference, so you don't duplicate CSS. In theory, that CSS file would get downloaded once, cached, and then the custom elements would each be able to use the classes in it (as long as they each link to it).

TylerH
  • 20,799
  • 66
  • 75
  • 101
charliepark
  • 1,480
  • 2
  • 13
  • 15
3

Take a look at this lesser known method:

The <core-style> Polymer element

You can define the styles in an html import file:

<core-style id="x-test">
  :host {
    backgound-color: steelblue;
  }
</core-style>

And then you can use them in more than 1 element:

<polymer-element name="x-test" noscript>
  <template>
    <core-style ref="x-test"></core-style>
    <content></content>
  </template>
</polymer-element>

In this well written article you can read more about how to use the technique.

However, a disadvantage I can think of is the impossibility of using SASS with this technique, since the styles are defined inside a <core-style> tag and not inside a <style> element, and there isn't a clear way to import an external stylesheet.

Cristian
  • 5,877
  • 6
  • 46
  • 55
1

I think I understand what you ask about. You can use link in every custom element to include your main styles or extend existing element that includes it. For example (using Polymer):

<polymer-element name="ui-button" noscript>
  <template>
    <link rel="stylesheet" href="main.css"/>
    <div class="class-from-main" style="">
      <content></content>
    </div>
  </template>
</polymer-element>

I think it worth reading to you: https://github.com/necolas/normalize.css/issues/408

Timur Fayzrakhmanov
  • 17,967
  • 20
  • 64
  • 95
0

Here's one example of it working : http://jsbin.com/zayih/1/edit?html,css,output

Though it does not seem to work when targeting it with #placeholder

Turn on "Show user agent shadow DOM" in Chrome devtools config tab, then inspect the <input> to see what I mean

elzi
  • 5,442
  • 7
  • 37
  • 61