One Thing @scope Can Do is Reduce Concerns About Source Order

Chris Coyier Chris Coyier on

There is an already-classic @scope demo about theme colors. Let’s recap that and then I’ll show how it relates to any situation with modifier classes. (The @scope rule is a newish feature in CSS that is everywhere-but-Firefox, but is in Interop 2025, so shouldn’t be too long to be decently usable.)

There are lots of different ways to implement color themes, but imagine a way where you do it with class names. I think it’s a valid way to do it, rather than, say, only responding to system preferences, because the classes might give you some on-page control. So you apply a theme at the top level. Then perhaps you have some elements that have other themes. Perhaps your site footer is always dark.

<body class="theme-light">
  <main>
    ...
  </main>
   
  <footer class="site-footer theme-dark">
    &copy;2025 <a href="/">Frontend Masters</a>
  </footer>
</body>Code language: HTML, XML (xml)

You set up those classes with colors, including other elements that need colors depending on that theme.

.theme-dark {
  background: black;
  color: white;

  a {
    color: #90caf9;
  }
}

.theme-light {
  background: white;
  color: black;

  a {
    color: #1976d2;
  }
}Code language: CSS (css)

There is already a problem with the HTML and CSS above.

The <a> in the footer will have the color of the light theme, not the dark theme. This is that classic @scope demo you’re likely to see a lot (sorry). This is because of source order. The selector .theme-light a has the exact same specificity as .theme-dark a but the light theme comes after so it “wins”.

One change to the above CSS will fix this:

@scope (.theme-dark) {
  background: black;
  color: white;

  a {
    color: #90caf9;
  }
}

@scope (.theme-light) {
  background: white;
  color: black;

  a {
    color: #1976d2;
  }
}
Code language: CSS (css)

This is referred to as proximity. It’s like a new part of the cascade (Bramus has a nice diagram here). Above, because the specificity is the same in both cases, the closer-in-the-DOM proximity “wins”. And closer meaning “fewest generational or sibling-element hops”. Like:

So, appropriately, the link styling nested under @scope (.theme-dark)wins because the specificity is the same but the proximity of the theme-dark class is closer.

What I like about this is that now the source order for those themes doesn’t matter. That’s nice as sometimes that’s hard to control. A good bundler should maintain source order after building, but perhaps these “variation classes” are in different files and the way they get built and loaded isn’t entirely predictable. Perhaps some lazy loading gets involved or the built files are purposefully spit or who-knows-what. I’ve seen too many “it’s fine on dev but broken on prod” bugs for one lifetime.

Color themes was just an excuse to look at variation classes.

Here’s another example:

.card-big {
  padding: 2rem;
}

.card {
  padding: 1rem;
}Code language: CSS (css)

Without even looking at HTML, you might consider this a “mistake” because, probably, card-big is a variation class of .card, except the thing that should be an override (the padding) won’t actually be overridden because of source order and equal specificity. I’d guess we all have some muscle memory for just ordering variation classes properly so this isn’t a problem, but it’s not ideal to me that we have to remember that, and that build tools and loading strategies might interfere anyway.

Here’s some real-world-ish CSS I was playing with where I could use @scope to put my variation class first without worry:

@scope (.card-big) {
  :scope {
    grid-column: span 2;
    display: flex;

    img {
      width: 50%;
      height: 100%;
    }
  }
}

.card {
  img {
    width: 100%;
    aspect-ratio: 16 / 9;
    object-fit: cover;
  }
}Code language: CSS (css)

Now if I’ve got two cards…

<div class="card">
  ...
</div>

<div class="card card-big">
  ...
</div>Code language: HTML, XML (xml)

I can rest easy knowing the .card-big styles will apply and appropriately override because of the proximity of the class to the things I want to style (including itself!)

Wanna learn CSS from a course?

Frontend Masters logo

FYI, we have a full CSS learning path with multiple courses depending on how you want to approach it.

7-Day Free Trial

Did you know?

Frontend Masters Donates to open source projects. $363,806 contributed to date.