Skip to content

[css-scoping-1] Clarify exactly what :host(<sel>) can use as argument #7953

@tabatkins

Description

@tabatkins

The :host() definition says:

When evaluated in the context of a shadow tree, it matches the shadow tree’s shadow host if the shadow host, in its normal context, matches the selector argument. In any other context, it matches nothing.

This allows you to do things like :host(.foo) to test if the host element has the foo class, which you can't tell from within the shadow because the host is featureless.

The selector argument is specified to only be a compound selector, with the intention that it only needs to look at the host element itself to match. (This was intentional and is the difference between it and :host-context().) But technically selectors like :is(.foo .bar) and :has(> .foo) are also compound selectors, tho they contain complex selector arguments. Per the grammar they're allowed, but should they be? If they should be, should we just drop the <compound-selector> restriction and go with a plain <selector>? (This is a pretty general question for <compound-selector> arguments in other locations, too.)

Further, the intention of :host() when I wrote it was just to "de-cloak" the host element, but to do so I phrased the selector as matching "in [the host element's] normal context". This can be read as implying that :host(:has(> .foo)) tests if the host element has a light dom child with the foo class, and in fact Safari does exactly this, while Chrome doesn't. (Compare with :host:has(> .foo), which definitely tests if a shadow dom child has a foo class.) Should this be considered correct?

(Context: Reddit is apparently depending on the Safari behavior to style a slot element differently based on whether something is slotted into it or not, using a selector like :host(:has(> [slot="foo"]) slot[name="foo"]. Without this behavior they'd have to listen for slotchange events and manually toggle a class on the slot element.)


So in short:

  1. Should a selector with a <compound-selector> argument allow complex selectors to be "smuggled in" via :is() and :has()? If so, should we just drop the restriction entirely?
  2. If the answer to 1 is "yes, allow them", should :host() literally evaluate its selector argument in the host tree, so its light-dom ancestors/descendants are visible to :host(:is(...)) and :host(:has(...))?

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions