Re: Shadow tree style isolation primitive

> On Jan 12, 2015, at 1:28 PM, Tab Atkins Jr. <jackalmage@gmail.com> wrote:
> 
> 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.

Another alternative.  We can add a host language dependent mechanism such as an element or an attribute to "end" the current isolation, just like insertion points in a shadow DOM would.
Better yet, we can provide this mechanism in CSS. e.g.

@isolate foo integrates(bar) {
  ...
}

@isolate bar {
  ...
}

(I'm not proposing this exact syntax. We can certainly do better.)

> 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.

There is a huge benefit in providing declarative alternative.  There are many use cases in which style/selector isolations are desirable on an existing element such as section and article elements.

> 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.

Let's not conflate style isolation with isolation of DOM subtrees.  They're two distinct features.  Even though I do agree it might be desirable to have both in many important use cases, there are use cases in which we don't need subtree isolations.

- R. Niwa

Received on Monday, 12 January 2015 22:15:10 UTC