RE: Shadow tree style isolation primitive

± On Fri, Jan 9, 2015 at 5:40 AM, Anne van Kesteren <annevk@annevk.nl>
± wrote:
± > I'm wondering if it's feasible to provide developers with the
± > primitive that the combination of Shadow DOM and CSS Scoping provides.
± > Namely a way to isolate a subtree from selector matching (of document
± > stylesheets, not necessarily user and user agent stylesheets) and
± > requiring a special selector, such as >>>, to pierce through the
± > boundary.
± >
± > This is a bit different from the `all` property as that just changes
± > the values of all properties, it does not make a selector such as
± > "div" no longer match.
± >
± > So to be clear, the idea is that if you have a tree such as
± >
± >   <section class=example>
± >     <h1>Example</h1>
± >     <div> ... </div>
± >   </section>
± >
± > Then a simple div selector would not match the innermost div if we
± > isolated the section. Instead you would have to use section >>> div or
± > some such. Or perhaps associate a set of selectors and style
± > declarations with that subtree in some manner.
± 
± It's probably feasible, sure.  But I'm not sure that it's necessary, or that
± browsers will go for it.  Using a shadow root as the isolation boundary is
± *really convenient*, because it's a separate tree entirely; the fact that
± outside rules don't apply within it, and inside rules don't apply outside, falls
± out for free.
± 
± Let's assume we did it, though.  We'd have to have some mechanism for
± defining an isolation boundary, and denoting whether rules were "inside" or
± "outside" the boundary.  This sounds like an at-rule,
± like:
± 
± @isolate .example {
±   h1 { ... }
±   div { ... }
± }
± 
± Now, a problem here is that you have a conflict between nesting isolated
± things and specifying isolation.  Say you have <foo> and <bar> elements,
± both of which need to be isolated. You'd think you could just write:
± 
± @isolate foo {
±   ...
± }
± @isolate bar {
±   ...
± }
± 
± But this won't work! If you have markup like <foo><bar>...</bar></foo>, the
± <bar> there is inside the <foo>'s isolation boundary, so the @isolate rule
± can't find it.  You'd need to
± *also* nest the "@isolate bar" rule (and all its styling rules) within the foo
± one, and vice versa.  The effect of this on *three* mutually isolated
± components is, obviously, terrible; let's not even mention trying to use
± multiple modules together that weren't explicitly designed together.
± 
± Alternately, say that it does work - the @isolate selector pierces through
± isolation boundaries.  Then you're still screwed, because if the outer page
± wants to isolate .example blocks, but within your component you use
± .example normally, without any isolation, whoops!
± Suddenly your .example blocks are isolated, too, and getting weird styles
± applied to them, while your own styles break since they can't cross the
± unexpected boundary.
± 
± Basically, trying to smuggle private state into a global declarative language is a
± bitch.
± 
± So, CSS is out.  We can't reasonably do this within the confines of CSS
± application.  It needs to be handled at a different layer.  We could do it in
± HTML, potentially - some new global attribute that creates a styling boundary
± that prevents outside styling from targeting anything inside.  Then you can
± just use standard <style
± scoped> to apply your own styles within the boundary - as long as the
± scoping root is inside the boundary, styling is allowed.
± 
± But that means you have to add an attribute to every element that uses this
± styling boundary, and move your style info into inline scoped blocks.  That's
± annoying. :/
± 
± Let's check out JS. If you can mark some elements as always being styling
± boundaries, then whenever they're constructed, whether manually or via
± the parser, they'll get the right mechanics automatically.  And since this is JS,
± it shouldn't be too hard to say "always attach this stylesheet to the element
± whenever it gets created", or perhaps introduce some explicit ability to do
± this in the platform.
± 
± This last one, though, is pretty much exactly Custom Elements, just with the
± children staying in the light tree rather than being moved into a shadow tree.
± But keeping them in the light tree has complications; it means that
± everything in the platform needs to be made aware of the isolation
± boundary.  Should qSA respect the isolation boundaries or not?  Depends on
± what you're using it for.
± What about things that aren't CSS at all, like getElementsByTagName()?
±  That's equivalent to a qSA with the same argument, but it's not a "selector",
± per se.  Manual tree-walking would also need to be made aware of this, or
± else you might accidentally descend into something that wants isolation.
± Shadow DOM at least gives an answer to all of these, by putting the
± elements in a separate tree.  You don't need to think of every one
± individually, or deal with inconsistent design when someone forgets to spec
± their new tree-searching thing to respect the boundary.
± 
± So, do you still think it's worth it to try to subdivide the functionality further? I
± think it's packaged in a reasonable way at the moment.
± 
± ~TJ

FWIW, I agree with this analysis. I think the objectives here are better served by using a Shadow DOM or a CSS+DOM-rewriting tool adding a class on each elements based on the stylesheets that should apply on them (this could be easily achieved using grunt). 


That being said, a process similar to the grunt one could be allowed in CSS, too. 

 @disable-mode(name) .dark-dom;
 @enable-mode(name) .dark-dom > .light-dom;
 @toggle-mode(name) .toogle-light-dom;
 
 @mode(name) {
     /* rules here only apply for elements whose 'name' mode is enabled */
 }

I don't think this is a great idea, though. It adds new complexity to CSS (a second matching phase) which I don't think is worthwhile. 

Received on Monday, 12 January 2015 22:48:03 UTC