Bug 16519 - [Shadow]: ":host" requires further clarification
[Shadow]: ":host" requires further clarification
Status: RESOLVED FIXED
Product: WebAppsWG
Classification: Unclassified
Component: Component Model
unspecified
PC All
: P2 normal
: ---
Assigned To: Dimitri Glazkov
public-webapps-bugzilla
:
Depends on:
Blocks: 16009
  Show dependency treegraph
 
Reported: 2012-03-26 07:02 UTC by Roland Steiner
Modified: 2012-06-15 21:05 UTC (History)
0 users

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Roland Steiner 2012-03-26 07:02:55 UTC
As stated in section 5.4, :host matches an element outside of the tree in which it is declared. I.e., if declared within a shadow tree, then it must match the host element in the host element's tree.

Section 7 essentially states that only rules within <style scoped> are applicable when declared in a shadow tree, but not rules from a simple <style> element.

However, the host element can never be a descendant of the scoping element of any <style scoped> within the shadow DOM, and therefore :host can never match in a rule within such a <style scoped>.

That would mean, that the only place where :host matches as written would be in a rule declared in the host element's tree, outside of the shadow DOM - but this doesn't seem to be the intent of 5.4.
Comment 1 Dimitri Glazkov 2012-03-26 16:26:13 UTC
There's a difference between a rule applying in a subtree and a rule matching an element. If a rule doesn't apply, it's just dropped. If it does apply, it could certainly match an element outside of the subtree. Does this make sense?

How can I make this distinction stronger? Perhaps change "apply" to "valid"?
Comment 2 Roland Steiner 2012-03-27 00:53:54 UTC
The question is different: a rule inside shadow DOM that isn't in <style scoped> does not apply. And if it is inside <style scoped>, :host can never match as the host element is outside the scope. Ergo, :host cannot possibly match at all (!) if used in rules inside the shadow DOM.

This outcome doesn't seem to me the intent of 5.4.
Comment 3 Dimitri Glazkov 2012-03-27 01:53:36 UTC
(In reply to comment #2)
> The question is different: a rule inside shadow DOM that isn't in <style
> scoped> does not apply. And if it is inside <style scoped>, :host can never
> match as the host element is outside the scope. 

Why? I just invented a new selector, surely I can invent a new behavior for it? :)

Ergo, :host cannot possibly
> match at all (!) if used in rules inside the shadow DOM.
> 
> This outcome doesn't seem to me the intent of 5.4.
Comment 4 Roland Steiner 2012-03-27 02:47:22 UTC
(In reply to comment #3)
> Why? I just invented a new selector, surely I can invent a new behavior for it?
> :)

Impossible is nothing, of course :) but I do think it could open quite a can of worms:

That would mean the presence of :host allows a selector to exceed the scoping element (where FWIW we've decided against this with :scope and :root and went with @global instead). But not only that, it would allow a rule to STYLE an element outside the scope - at least I suppose that's the main purpose (?) - something that's not even possible with @global.

Allowing access to the host element looks even fishier if the <style scoped> in question is not a direct child of the ShadowRoot, but happens to be at some arbitrary point within the shadow DOM, where there are elements "in between".

Lastly, it also raises the question what, e.g. ":host div" means (or whether it's allowed).

To be sure, I don't have any good answer for all of this either. Dropping the requirement to ignore non-scoped <style> elements could resolve it.

Another brainstorming thought: what about a @host rule instead? This would have the advantage that the breaking behavior is explicit, and makes sure only the host element is affected (rules inside @host can match the host element only) E.g.:

@host {
  div { background-color: white; }
  .warning { background-color: yellow; }
  .important .warning { background-color: orange; }
}
Comment 5 Dimitri Glazkov 2012-03-27 16:22:01 UTC
(In reply to comment #4)

> Another brainstorming thought: what about a @host rule instead? This would have
> the advantage that the breaking behavior is explicit, and makes sure only the
> host element is affected (rules inside @host can match the host element only)
> E.g.:
> 
> @host {
>   div { background-color: white; }
>   .warning { background-color: yellow; }
>   .important .warning { background-color: orange; }
> }

I like this.
Comment 6 Dimitri Glazkov 2012-06-15 20:05:19 UTC
(In reply to comment #5)

> > @host {
> >   div { background-color: white; }
> >   .warning { background-color: yellow; }
> >   .important .warning { background-color: orange; }
> > }
> 
> I like this.

One use case that I came across was the need to react to DOM tree of the host element. For instance, there's a body.loading -> body.loaded transition that commonly occurs to indicate that the document has arrived to some stable state.

The shadow DOM subtrees may want to know about this transition (for example, the widgets on the page would change appearance reflecting arrival to a stable state.

I see a developer expecting to do something like this in the shadow DOM subtree:

body.loading :host div.foo { ... }

body.loaded :host div.foo { ... }

Where: 

* "body.loading", "body.loaded", and ":host" are matched in the subtree of the host element
* div.foo are matched in the shadow subtree.

Clearly, this is wrong. The subtree of host element could be another shadow DOM subtree, which means that these selectors will not match.

Perhaps I should tackle this a separate issue.
Comment 7 Dimitri Glazkov 2012-06-15 21:05:31 UTC
(In reply to comment #5)
> (In reply to comment #4)
> 
> > Another brainstorming thought: what about a @host rule instead? This would have
> > the advantage that the breaking behavior is explicit, and makes sure only the
> > host element is affected (rules inside @host can match the host element only)
> > E.g.:
> > 
> > @host {
> >   div { background-color: white; }
> >   .warning { background-color: yellow; }
> >   .important .warning { background-color: orange; }
> > }
> 
> I like this.

http://dvcs.w3.org/hg/webcomponents/rev/32a744c2c2f9

Please reopen bug if I did this poorly.