This is an archived snapshot of W3C's public bugzilla bug tracker, decommissioned in April 2019. Please see the home page for more details.
Currently selectors in shadowRoot styles match the host element. This makes it relatively easy to write rules that have unexpected, undesired effects. Consider a shadowRoot like this: <style> #thing { background: red; } </style> <div id="thing">sr-div</div> The author has setup an id based style that should apply only within this shadowRoot. Now that shadowRoot is added to an element like this: <div id="#thing">host-div</div> Now both host-div and inside-div will be styled via #thing which is not what the shadowRoot author wanted or expects. To fix this, we can make the :host the only way to match the shadowRoot host element.
oy vey. Didn't we just all agree that it _should_ match? http://lists.w3.org/Archives/Public/public-webapps/2013AprJun/0985.html
Yeah, we did agree that this should match (big sigh). I think that was a mistake and we now have a wart on an otherwise pretty face. I'd be happy to be convinced otherwise. My main concern is that ShadowDOM authors will have to defend against accidentally having styles match host by not writing simple selectors. Imagine rules like this inside a shadowRoot style element. The author intends to match elements inside the shadowRoot: #container { border: 1px solid black; } .rounded { border-radius: 10px; } If the host incidentally matches one of those selectors, things will blow up. To avoid this the ShadowDOM author is forced to always write: :host #container {...} :host .rounded {...} That seems pretty unfortunate doesn't it? Am I missing a virtue of having these styles match the host element? It seems like we have the host element well covered via :host.
Tab, Hayato-san, Sakamoto-san, WDYT?
There's no sane way to make host styleable only when you specifically want it without violating Selector semantics, as we found out earlier. Saying that only :host can match a host element violates Selector semantics, because pseudo-classes are just impl-defined classes; that is, they merely filter the available elements, they don't add new elements to the set. :/
Does this address the selector semantics concern? 1. the host element is in the set of elements that selectors in shadowRoot styles can match. 2. any selector that does not contain :host cannot match the host element. If so, this gives us the best of both worlds, e.g. #container, .rounded { /* matches only elements inside shadowRoot, not the host element */ } .rounded:host { /* matches only the host element if it has the `rounded` class */ } .special:host > div { /* matches div children of the shadowRoot if the host element has a `special` class */ }
(In reply to comment #5) > Does this address the selector semantics concern? > > 1. the host element is in the set of elements that selectors in shadowRoot > styles can match. > 2. any selector that does not contain :host cannot match the host element. No, saying "X is in the set of elements, but it's impossible to select unless you tack this pseudo-class on" is identical to "using this pseudo-class adds X to the set of elements". Selectors, pseudo-classes included, are just filters. Combinators transform the set of elements via whatever relation they define. (Pseudo-elements are included in this, just with a syntax that's slightly different than other combinators.) We tried to use a combinator to separate the host from the inner elements, but it was all terribly clumsy. :/
(In reply to comment #6) > (In reply to comment #5) > > Does this address the selector semantics concern? > > > > 1. the host element is in the set of elements that selectors in shadowRoot > > styles can match. > > 2. any selector that does not contain :host cannot match the host element. > > No, saying "X is in the set of elements, but it's impossible to select > unless you tack this pseudo-class on" is identical to "using this > pseudo-class adds X to the set of elements". Selectors, pseudo-classes > included, are just filters. Can't you add a layer of sugar? Host is in the set by default. In the (possibly unwriteable) primitives there's :except-host which removes host from the set. In the sugared layer, every rule is desugared to add :except-host. Unless the rule contains :host. Then it the desugaring just removes :host (because it is not primitive syntax, because it violates those things you were worried about) and hence host remains in the set.
(In reply to comment #7) > Can't you add a layer of sugar? Host is in the set by default. In the > (possibly unwriteable) primitives there's :except-host which removes host > from the set. > > In the sugared layer, every rule is desugared to add :except-host. Unless > the rule contains :host. Then it the desugaring just removes :host (because > it is not primitive syntax, because it violates those things you were > worried about) and hence host remains in the set. We don't desugar CSS yet (beyond conceptual explanations), so this probably won't fly. Plus, it's just a way to pretend that we're not making :host magical. :/ Look, if this is *actually* something you want, then what you're doing is changing the context the selector is evaluated in. That means removing the host from the set of elements normally, and having an at-rule - @host - which adds it back for its contained selectors. (Or the other way around, obviously.) Or, we can just assume that we'll actually add CSS Nesting at some point, and live with the fact that wrapping rules in an ":host {...}" will protect you: :host { .foo { /* won't accidentally select the host */ } #bar { /* this either */ } }
Sounds like there isn't an obvious and non-awkward solution. I'd hate to drag everyone back into another meeting, but this might be the best way to solve this expeditiously.
I've just read the discussion. I don't have any idea either. Let me sync up with @tasak for some ideas.
Here is an example of why rules matching the host element is problematic (requires ShadowRoot enable browser, e.g. chrome): http://jsbin.com/UgirokO/5/edit
The above jsbin should be run in at least Chrome 30 (as of this writing, that's the Chrome Canary).
Oops, sorry, the Experimental Web Platform features flag must also be enabled.
Speaking with my web developer hat on, I was very confused when the styles inside my shadow were leaking out into the host context. It defeats a lot of the point of trying to get isolation. Maybe we need a different syntax than :host to keep CSS selector semantics happy, but the currently solution is worse than violating CSS selector semantics IMO.
This discussion looks obsolete. The style in shadow trees might match the host element, using ':host' pseudo classes. Let me close this bug.