Testing

CSS @scope: Browser Support, Cascade, Donut Scope

CSS @scope works in Chrome 118+, Edge 118+, Opera 106+, Safari 17.4+ on macOS and iOS, Samsung Internet 25+, and Firefox 146+. Learn cascade and quirks.

Author

Prince Dewani

May 6, 2026

CSS @scope is a W3C cascade at-rule that confines a block of selectors to a DOM subtree, with an optional lower limit that creates a donut-shaped match region. It works in Chrome 118+, Edge 118+, Opera 106+, Samsung Internet 25+, Safari 17.4+ on macOS and iOS, and Firefox 146+, while Internet Explorer never supported it.

This guide covers what CSS @scope is, the browsers that support it, donut scope, the cascade rules, feature detection, and known production issues.

What is CSS @scope?

CSS @scope is a W3C Cascade and Inheritance Level 6 at-rule that scopes a block of style rules to a chosen DOM subtree. You set a scope root selector for the upper bound and an optional scope limit for the lower bound, and the rules only match elements between them.

Which browsers does CSS @scope support?

Every modern Chromium-based browser, Safari, and Firefox now supports CSS @scope by default. Firefox was the last major engine to ship it, and Internet Explorer never added the at-rule.

Loading browser compatibility data...

CSS @scope compatibility in Chrome

Chrome supports CSS @scope by default from Chrome 118 on Windows, macOS, Linux, ChromeOS, and Android. Chrome 104 to 117 had @scope hidden behind the Experimental Web Platform Features flag at chrome://flags. Chrome 4 to 103 did not support the at-rule at all.

CSS @scope compatibility in Edge

Microsoft Edge supports CSS @scope from Edge 118 across Windows, macOS, Linux, Android, and iOS. Edge 104 to 117 hid it behind the same Experimental Web Platform Features flag at edge://flags. The legacy EdgeHTML browser does not support @scope and never will.

CSS @scope compatibility in Firefox

Firefox supports CSS @scope from Firefox 146 on Windows, macOS, Linux, and Android. Firefox 1 to 145 did not support the at-rule, so any older Firefox build silently ignores @scope blocks and falls through to the surrounding rules without any scoping applied.

CSS @scope compatibility in Safari

Safari supports CSS @scope from Safari 17.4 on macOS Sonoma 14.4 and later, and from Safari 17.4 on iOS and iPadOS 17.4 and later. Safari 1 to 17.3 on macOS, plus iOS 1 to 17.3, do not support @scope. The Safari implementation matches the spec for scope roots, scope limits, and the proximity cascade rule.

CSS @scope compatibility in Opera

Opera supports CSS @scope from Opera 106 on Windows, macOS, Linux, and Android. Opera 90 to 105 had @scope disabled by default behind the Experimental Web Platform Features flag at opera://flags. Opera Mobile supports @scope from Opera Mobile 80 on Android.

CSS @scope compatibility in Samsung Internet

Samsung Internet supports CSS @scope from Samsung Internet 25 on Galaxy phones and tablets. Versions 4 to 24 did not support the at-rule. The implementation tracks Chromium, so the cascade and proximity rules behave the same as in Chrome for Android.

CSS @scope compatibility in Android Browser

Chrome for Android supports CSS @scope from Chrome 118 on Android 8.0 and later. The legacy stock Android Browser, used on Android 4.4 and earlier, never added @scope. On modern Android devices, Chrome, Firefox for Android, and Samsung Internet all parse @scope by default.

CSS @scope compatibility in Internet Explorer

Internet Explorer does not support CSS @scope in any version. Microsoft has retired Internet Explorer, and the @scope at-rule was specified long after IE 11 stopped getting feature work. Sites that still target IE need a CSS bundle that does not rely on @scope.

Note

Note: CSS @scope behaves slightly differently across Chrome, Safari, and Firefox cascade engines. Test it on real browsers and OS with TestMu AI. Try TestMu AI free!

What is donut scope in CSS @scope?

Donut scope is the most useful pattern @scope unlocks. You pass a scope root selector and a scope limit selector to the @scope prelude, and the rules only match elements that sit between the two boundaries. The donut shape comes from the gap: elements outside the root and elements inside the limit both fall out of the match set.

A typical donut scope looks like this:

@scope (.card) to (.card__content) {
  img { border-color: green; }
}

The rule turns every img green inside .card, but stops at .card__content. Images nested deeper than .card__content keep their default border. This is exactly what a component author wants when an inner slot embeds a child component with its own image styles. The donut keeps the parent component styling out of the inner slot, while still applying it to everything else inside the root.

How does @scope affect the CSS cascade?

@scope adds a new step to the cascade called scoping proximity. When two rules tie on specificity, the rule whose scope root sits closer to the matched element wins, no matter what order they appear in the source. Proximity sits between specificity and order of appearance in the cascade, so a less specific selector inside a closer scope can beat a more specific selector inside an outer scope.

The :scope pseudo-class targets the scope root itself and adds (0,1,0) of specificity. Selectors inside a scoped block get an implicit :scope prepended, so a bare img selector behaves like .card img inside @scope (.card). The & nesting selector inside @scope also points at the scope root, but it composes like a normal nested selector and can match the root from anywhere the selector applies, while :scope only matches the root once.

How do you check if a browser supports CSS @scope?

Use the @supports at-rule, the CSS.supports JavaScript API, or a quick DevTools probe to confirm the browser parses @scope before you ship a stylesheet that depends on it.

  • Open the page in your target browser: Load any page in the browser version you want to test, including older Safari and Firefox builds where @scope might be missing.
  • Open DevTools and switch to the Console: On Chromium and Firefox press F12, on Safari press Option-Command-I after you enable the Develop menu.
  • Run the CSS.supports probe: Paste the snippet below to print yes or no for both the @scope at-rule and the :scope pseudo-class.
  • Wrap dependent styles in @supports: Put fallback rules outside an @supports (at-rule: @scope) block, then put the @scope-only rules inside, so older browsers fall through to the fallback.
  • Confirm in the Styles pane: Inspect a scoped element and check that the rule shows the @scope prelude next to the selector. If the prelude is missing, the browser parsed @scope as an unknown at-rule and dropped the whole block.

Paste this snippet into the browser DevTools console to confirm @scope support:

// Run in any browser DevTools console to confirm @scope support.
const scopeAtRule = CSS.supports("at-rule: @scope");
const scopePseudo = CSS.supports("selector(:scope)");

console.log("@scope at-rule parsed:", scopeAtRule ? "yes" : "no");
console.log(":scope pseudo-class parsed:", scopePseudo ? "yes" : "no");

if (!scopeAtRule) {
  console.warn("This browser ignores @scope blocks. Ship a fallback stylesheet.");
}

If the at-rule check prints no, your fallback stylesheet should ship the same rules under BEM-style class names so layout still holds on older browsers.

...

What are the known issues with CSS @scope?

@scope reached baseline only after Firefox 146 shipped, so a long tail of older browsers still ignores the at-rule. The cascade changes also catch teams off guard when proximity flips a rule that worked under specificity alone.

  • Firefox was last to ship: Firefox 145 and earlier silently ignore @scope blocks. Visitors on long-term-support builds inside locked-down enterprises will not get scoped styles for a while, so a fallback stylesheet stays mandatory.
  • Safari 17.3 and older have no support: macOS Big Sur and Monterey are pinned to Safari 15 and 16, which do not parse @scope. iPhone visitors on iOS 17.3 or earlier hit the same gap.
  • :scope and & differ in subtle ways: :scope matches the root once with specificity (0,1,0), while & resolves like a nested selector and can match across the subtree. Mixing the two inside one block produces specificity surprises that DevTools surfaces only after layout breaks.
  • Proximity can flip expected wins: A less specific rule inside a closer scope beats a more specific rule from an outer scope. Teams used to specificity-only cascade reasoning need to retrain on proximity before they ship deeply nested @scope hierarchies.
  • No working JavaScript polyfill: @scope is a parser-level at-rule, so a JS shim would have to re-parse and rewrite stylesheets on every load. That breaks DevTools and adds startup cost no team wants in production.
  • Prelude-less @scope only works inline: A bare @scope block scopes to the parent of its style element only when the block lives inside an HTML style element. The same block in an external CSS file applies nothing because it has no scope root to bind to.
  • DevTools display varies: Chrome shows the @scope prelude in the Styles pane, Safari Web Inspector shows it more compactly, and Firefox 146 surfaces it in a separate panel. Cross-browser debugging needs you to know each tool layout.

In my experience, the most surprising failure happens on iOS 17.3. Safari parses the @scope keyword as an unknown at-rule and drops the whole block, including the rules that should fall through, so the page renders with no styles where the scoped rules used to apply. Always pair an @scope block with an @supports fallback when you target iPhone visitors.

...

Citations

All CSS @scope version numbers and platform notes in this guide come from these primary sources:

Author

Prince Dewani is a Community Contributor at TestMu AI, where he manages content strategies around software testing, QA, and test automation. He is certified in Selenium, Cypress, Playwright, Appium, Automation Testing, and KaneAI. Prince has also presented academic research at the international conference PBCON-01. He further specializes in on-page SEO, bridging marketing with core testing technologies. On LinkedIn, he is followed by 4,300+ QA engineers, developers, DevOps experts, tech leaders, and AI-focused practitioners in the global testing community.

Open in ChatGPT Icon

Open in ChatGPT

Open in Claude Icon

Open in Claude

Open in Perplexity Icon

Open in Perplexity

Open in Grok Icon

Open in Grok

Open in Gemini AI Icon

Open in Gemini AI

Copied to Clipboard!
...

3000+ Browsers. One Platform.

See exactly how your site performs everywhere.

Try it free
...

Write Tests in Plain English with KaneAI

Create, debug, and evolve tests using natural language.

Try for free

Frequently asked questions

Did you find this page helpful?

More Related Hubs

TestMu AI forEnterprise

Get access to solutions built on Enterprise
grade security, privacy, & compliance

  • Advanced access controls
  • Advanced data retention rules
  • Advanced Local Testing
  • Premium Support options
  • Early access to beta features
  • Private Slack Channel
  • Unlimited Manual Accessibility DevTools Tests