@scope just landed in Firefox 146! This gives us real style scoping without needing Shadow DOM or BEM naming conventions.

The problem it solves

CSS has always been global. You write .card { padding: 1rem } and every card everywhere gets that padding. We’ve worked around this with:

  • BEM naming (.article-card__title--featured)
  • CSS Modules (build-time class name hashing)
  • Shadow DOM (full encapsulation, but heavy)

@scope gives us a native way to say “these styles only apply within this subtree.”

Basic syntax

@scope (.card) {
  h2 {
    font-size: 1.5rem;
  }

  p {
    color: gray;
  }
}

These styles only affect h2 and p elements inside .card. Simple as that.

The “donut scope” pattern

Here’s where it gets interesting. You can set both upper AND lower bounds:

@scope (.article) to (figure) {
  img {
    border: 2px solid black;
  }
}

This styles all images inside .article… except those inside figure elements. It’s called “donut scope” because you’re selecting a ring around the excluded center.

Perfect for component libraries where you want to style a container but leave nested components alone.

Scope proximity

When scopes overlap, the closest scope wins:

@scope (.light-theme) {
  p { color: black; }
}

@scope (.dark-theme) {
  p { color: white; }
}
<div class="light-theme">
  <p>Black text</p>
  <div class="dark-theme">
    <p>White text</p>
    <div class="light-theme">
      <p>Black text (closer to .light-theme)</p>
    </div>
  </div>
</div>

No more fighting with specificity to get nested themes right.

The :scope selector

Inside a @scope block, :scope targets the root element itself:

@scope (.feature) {
  :scope {
    background: rebeccapurple;
    padding: 2rem;
  }

  h2 {
    color: white;
  }
}

Inline scoping

You can scope styles right where they’re used:

<div class="widget">
  <style>
    @scope {
      p { color: blue; }
    }
  </style>
  <p>This is blue</p>
</div>
<p>This is not</p>

When you omit the scope root in a <style> tag, it automatically scopes to the parent element.

Browser support

As of December 2025:

  • Chrome/Edge: 118+
  • Safari: 17.4+
  • Firefox: 146+ (just shipped!)

We finally have cross-browser support for native CSS scoping.