picostitch
crafting (and) JavaScript

Inline @scope for CSS

I am not tightly following what's going on in CSS land, since blogs are not the thing and mailing lists became spam lists I don't know where to "listen". But from time to time I read MDN and look for the things that I expect CSS and HTML to provide. And funny enough, often my expectations and reality are aligned. Maybe because the missing things are just so obvious :).

One of these things is the @scope rule in CSS.

The "old" way - Styling via CSS Classes

We can do the following:

<style>
  .my-container * {...}
</style>
<section class="my-container">
  ...
</section>

We use a CSS class to apply a certain style to all children (.my-container *) of this section. If this is a one-of use case the class is quite useless and is sometimes just a made-up name, so it only exists because there is no other way.

Given the CSS is close to the HTML that is the only consumer of this CSS, not in a separate file, where maintenance tools are needed to keep them in sync, think about how much dead (CSS) code there is.

If the CSS and HTML are close there is a better way now.

The "new" way - Scoped CSS

With scoped CSS this can also be done like so:

<section>
  <style>
    @scope {...}
  </style>
  ...
</section>

This way the CSS is directly attached to the HTML and only applies to the children of this section. Basically @scope is saying apply the CSS only inside the DOM node I am in, which is here inside the section.

In Action

Let's see it in action.

<section>
  <style>
    @scope {
      :scope { color: red; } /* Styling the SECTION itself */
      span { color: blue; }
    }
  </style>

  <span>inside a SPAN = blue</span>
  <div>inside a DIV = inherited color = red</div>
  inside SECTION, but outside the SPAN = red
</section>

Outside of the SECTION, no red, no blue.

This will render like so (if you see no red and blue, see section "Support?" below):

inside a SPAN = blue
inside a DIV = inherited color = red
inside SECTION, but outside the SPAN = red

Outside the SECTION, no red, no blue.

You can see that @scope simply limits the styling to the children of the DOM node it is in. And the :scope selector is a way to style the node itself.

Scope Root and Limit

There is more that @scope can do: @scope (root) to (limit) which allows to limit the scope to a certain part of the DOM tree. Read more about it on MD.

Support?

See caniuse for the support, at the time of writing caniuse says 82% support globally. Sounds quite good.

Data on support for the css-cascade-scope feature across the major browsers from caniuse.com