CSS @scope Explained

CSS gets harder to manage when a site grows. You add a style for links inside a card, another rule changes links inside the footer, and later you discover that a selector written months ago is affecting something it was never meant to touch.

One common solution is to make selectors longer:

.page .main .card .content a {
  color: blue;
}

That works, but it ties the CSS closely to the HTML structure and can make later overrides harder.

CSS @scope gives us another option. It lets you say that a group of styles should only apply inside one part of the page.

The @scope rule reached Baseline 2026.

A basic scope

<article class="card">
  <h2>My article</h2>
  <p>Some text with <a href="#">a link</a>.</p>
</article>
@scope (.card) {
  a {
    color: tomato;
  }

  h2 {
    margin-top: 0;
  }
}

The link rule only applies to links inside .card.

It does not change links in the header, footer, or another part of the page.

Why not just write .card a?

For a small example, this is perfectly fine:

.card a {
  color: tomato;
}

@scope becomes more useful when a component has many internal rules.

Without scope:

.card h2 { ... }
.card p { ... }
.card a { ... }
.card img { ... }
.card ul { ... }

With scope:

@scope (.card) {
  h2 { ... }
  p { ... }
  a { ... }
  img { ... }
  ul { ... }
}

The intent is easier to see.

Using :scope

Inside a scope, :scope refers to the root element of that scope.

@scope (.notice) {
  :scope {
    padding: 1rem;
    border: 1px solid #ddd;
  }

  h2 {
    margin-block: 0 0.5rem;
  }
}

In this case, :scope means .notice.

Scope limits

You can also define where a scope should stop.

@scope (.article) to (.comments) {
  a {
    color: blue;
  }
}

The link style applies inside .article, but it stops when the browser reaches .comments.

That can be useful when a large area contains smaller parts that should manage their own styles.

A blog article example

<article class="post">
  <p>Normal article text.</p>

  <div class="demo">
    <a href="#">Demo link</a>
  </div>
</article>

You may want article links styled one way without affecting the demo:

@scope (.post) to (.demo) {
  a {
    text-decoration-thickness: 0.12em;
  }
}

Inline scopes

@scope can also be used in a <style> element placed inside a component.

<section class="card">
  <style>
    @scope {
      h2 {
        color: darkred;
      }
    }
  </style>

  <h2>Card title</h2>
</section>

The styles are scoped to the parent of the <style> element.

I would not use this everywhere, but it can be useful for small self-contained demos.

@scope and the cascade

@scope does not replace normal CSS rules. Specificity, source order, inheritance, and cascade layers still matter.

It simply limits where a selector can match.

That means it can also be combined with @layer:

@layer components {
  @scope (.card) {
    a {
      color: blue;
    }
  }
}

@scope answers where a style can apply.

@layer helps decide which group of styles wins.

Use a fallback when needed

Older browsers ignore @scope.

If the style is important, write a simple fallback first:

.card a {
  color: blue;
}

Then use scoped CSS as an improvement where supported.

Should you use it everywhere?

Probably not.

For a small site, this is often clearer:

.card a {
  color: blue;
}

I see @scope as most useful when:

The best thing about @scope is not that it saves characters. It lets the CSS describe its boundaries more clearly.

@scope (.card) {
  /* Card styles live here */
}

On larger sites, that can make a stylesheet much easier to understand.