🌐 US-Proxy
class="logged-out env-production page-responsive" style="word-wrap: break-word;" >
Skip to content

[css-scoping][css-cascade] :scope in shadowy prelude-less @scope matches nothing #9178

Closed

Description

@andruud

A prelude-less @scope rule, e.g. @scope { ... } scopes the styles to the root of the containing tree if the owner element has no parent element. Example:

<div class=host>
  <template shadowrootmode=open>
    <style>
      @scope {
        /* :scope is the _shadow root_ */
      }
    </style>
  </template>
</div>

However, the shadow root can't be matched by :scope, because it's replaced by the shadow host for selector purposes. CSS Scoping 1:

For the purpose of Selectors, a shadow host also appears in its shadow tree, with the contents of the shadow tree treated as its children. (In other words, the shadow host is treated as replacing the shadow root node.)

This makes prelude-less @scope rules that exist directly beneath a shadow root mostly non-usable, since the inner selectors either have :scope in them somewhere, or get an implicit :scope prepended if not.

Not sure what the best fix is here ...

@tabatkins


I noticed that https://drafts.csswg.org/css-scoping-1/#shadow-gloss contradicts the other part of the spec:

The elements in a shadow tree are not descendants of the shadow host in general (including for the purposes of Selectors like the descendant combinator). However, the shadow tree, when it exists, is used in the construction of the flattened element tree, which CSS uses for all purposes after Selectors (including inheritance and box construction).

But since this doesn't match browser implementations, I assume it's a remnant of a previous spec version.


EDIT: Related: #7261 (comment)

Activity

  1. andruud commented on Aug 11, 2023

    @andruud
    MemberAuthor

    Looking a bit closer at the specs, the most consistent thing might be to scope to the shadow host instead, though still match in the context of the shadow tree. So the scoping root is:

    1. The parent element of the owner node, if such an element exists
    2. Otherwise the shadow host, if the containing node tree is a shadow tree
    3. Otherwise the root of the containing node tree.

    EDIT: And we'd need to pair that with #9025, otherwise :scope wouldn't match in this case either.

  2. mirisuzanne commented on Aug 15, 2023

    @mirisuzanne
    Contributor

    Yes, this solution makes sense to me. I would expect this scope to be the shadow host.

  3. tabatkins commented on Aug 17, 2023

    @tabatkins
    Member

    Yes, this seems pretty clearly to just be an oversight; if the stylesheet is a root element of the shadow tree, it should scope to the shadow host. (And :scope should be able to match the host element in this instance, like & can (search for "featureless").) This effectively makes the @scope a no-op, I think, since shadow styles are always scoped to the shadow anyway? But it should def work, rather than breaking.

    I noticed that drafts.csswg.org/css-scoping-1/#shadow-gloss contradicts the other part of the spec:
    [snip]
    But since this doesn't match browser implementations, I assume it's a remnant of a previous spec version.

    Hm, yeah, that might predate some of the featureless text, or maybe it's just being too general, and meant like "you can't do my-component > .in-the-shadow". I'll tweak the wording.

  4. andruud commented on Aug 17, 2023

    @andruud
    MemberAuthor

    @astearns Proposed async resolution: @scope without <scope-start> scopes to the shadow host instead of the shadow root.

  5. added 2 commits that reference this issue on Aug 17, 2023
  6. added a commit that references this issue on Aug 17, 2023
  7. added 2 commits that reference this issue on Aug 17, 2023
  8. mirisuzanne commented on Aug 17, 2023

    @mirisuzanne
    Contributor

    I don't think this would necessarily make it no-op, since @scope has a cascade-priority aspect. It would still impact how styles scoped to the host element interact with differently-scoped (or unscoped) styles in the same shadow dom.

    Then again, the host is likely the default scope-root for un-scoped styles in shadow dom? So maybe that is still no-op?

  9. andruud commented on Aug 17, 2023

    @andruud
    MemberAuthor

    Yeah, scoping-wise it's a no-op, but you'd get proximity applied between the subject and the host.

  10. added a commit that references this issue on Aug 22, 2023
  11. astearns commented on Aug 22, 2023

    @astearns
    Member

    The CSSWG will automatically accept this resolution one week from now if no objections are raised here. Anyone can add an emoji to this comment to express support. If you do not support this resolution, please add a new comment.

    Proposed Resolution: @scope without <scope-start> scopes to the shadow host instead of the shadow root.

  12. 13 remaining items

  13. added a commit that references this issue on Sep 16, 2024
  14. added 2 commits that reference this issue on Sep 16, 2024
  15. added a commit that references this issue on Sep 24, 2024
  16. added a commit that references this issue on Sep 25, 2024
  17. moved this from Needs Edits to Done in Cascade 6 (Scope)on Feb 20, 2025
  18. added 2 commits that reference this issue on Sep 16, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Type

No type

Projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions