StealThis .dev

CSS @scope Theming

Two theme regions sharing identical class names, styled independently with native CSS @scope so tokens and rules never leak across subtrees — plus a donut-scope example that stops at a boundary.

Open in Lab
css
Targets: JS HTML

Code

This demo shows how the native CSS @scope at-rule confines styles and custom-property theme tokens to a subtree of the DOM, so two side-by-side product cards can share the exact same class names (.card, .badge, .cta) yet render with completely different brand palettes. Each region declares @scope (.brand-a) / @scope (.brand-b), and the tokens defined inside one scope never bleed into the other — no BEM prefixing, no CSS Modules, no !important arms race.

The third panel demonstrates donut scoping with the @scope (root) to (limit) syntax: styles apply to everything inside the outer boundary except the inner region past the lower limit, letting you theme a comment thread while leaving an embedded quote untouched. Interactive controls let you retune each brand’s accent hue live, toggle the donut hole on and off, and inspect the generated @scope block so you can see exactly what the browser is scoping.

It leans entirely on the platform @scope cascade feature. A @supports selector(:scope) feature detect drives a graceful fallback banner and attribute-scoped styling for browsers that haven’t shipped @scope yet, so the regions still theme correctly everywhere while clearly labeling when true native scoping is active.