Skip to content

[css-cascade] Allow making a scope's upper bound really inclusive (evaluate nested selectors against it) #13391

@benface

Description

@benface

MDN says:

The scope's upper bound is inclusive and its lower bound is exclusive. To change this behavior, you can combine either selector with a universal child selector. For example, @scope (scope root) to (scope limit > *) would make both bounds inclusive, @scope (scope root > *) to (scope limit) would make both bounds exclusive, while @scope (scope root > *) to (scope limit > *) would give an exclusive upper bound and an inclusive lower bound.

(emphasis mine)

I understand that "the scope's upper bound is inclusive" means that it is possible to style the scope's upper bound within the scope (i.e. with :scope or with &), but there are cases where I wish we didn't have to be explicit about it and just automatically evaluate the selectors of all nested rules against the root element. Here's what I mean, with an imagined new including keyword:

@scope including (.my-design-system) {
  .bg-primary { background-color: var(--ds-bg-primary); }
  /* other utility classes... */
}
<button type="button" class="my-design-system bg-primary">
  This button has the `--ds-bg-primary` background color!
</button>

Imagine we have hundreds or even thousands of such utility classes; this would prevent having to write their selector twice every time just in case one is used on the root:

@scope (.my-design-system) {
  .bg-primary, &.bg-primary { /* ... */ }
  .bg-secondary, &.bg-secondary { /* ... */ }
  /* etc. */
}

And why would we want to do that? Imagine we have a component library that uses these utility classes internally, but we don't want them to clash with the author/consumer's own CSS which we don't control (we'd probably also need some technique to isolate our scope from the rest of the page's styles), so we add a class (my-design-system) to all our components' root elements and wrap all of our library's CSS with @scope (.my-design-system)... but then sometimes we need to use a utility class on the root element of the component, not just inside it (whether it's just to get a flatter DOM structure, or because the utility affects the layout in a way that doesn't work if it's nested).

Hopefully this proposal resonates with others. 🤞

Metadata

Metadata

Assignees

No one assigned

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions