CSS @scope Playground
Edit HTML and CSS side by side and watch the @scope root and scope limit highlight live, so you can see exactly which elements are in and out before you ship it in a real component.
How the @scope playground works
- 1
Pick a preset or start typing
Load one of the three examples — a card with a nested component, a donut scope around a quote block, or the :scope pseudo-class — or edit the HTML and CSS panes directly. Every keystroke re-renders after a short debounce.
- 2
The CSS is rendered natively
Your styles are injected into a sandboxed iframe and the browser's own @scope engine applies them. There is no CSS parser or polyfill in between, so what you see is exactly how a real browser scopes your rules.
- 3
The scope boundary is read from your CSS
The tool reads the scope root and optional limit out of your first @scope rule and injects a matching highlight layer. Because that layer is itself an @scope rule, the browser decides which elements are in scope — the highlight can never disagree with real behavior.
- 4
In-scope elements get a green outline
The scope root is drawn with a solid green outline and every in-scope descendant with a dashed green outline. When a limit is set, the excluded element is outlined in red so you can see where the scope stops.
- 5
Toggle @scope off to see the leak
Flip to Without @scope and the tool strips the @scope wrappers, letting the same selectors apply globally. Paragraphs outside the component suddenly change color — the exact problem @scope was designed to prevent.
- 6
Copy the snippet
Use Copy CSS or Copy HTML to lift the current example straight into your project. Nothing leaves your browser.
What the highlight colors mean
Turn on Highlight scope boundary and the preview draws three states. Each one answers a different question about your scope.
Scope root — solid green
Always present when your CSS has a valid @scope rule.
The single element that matches the scope root selector. Everything the scope can reach starts here. If you expected an outline and see none, your root selector matches nothing in the current HTML.
In-scope descendant — dashed green
Any element under the root that the scope still reaches.
These are the elements your scoped selectors can target. Add a scope limit and watch some of these dashed outlines disappear as those elements drop out of the zone.
Excluded (past the limit) — dashed red
Only appears when you set a scope limit with to (...).
The limit element marks the top of the donut hole. It, and everything inside it, is cut out of the scope. Your scoped rules cannot style anything from this red outline downward.
@scope syntax reference
Every form the playground understands. Paste any of these into the CSS pane.
| Syntax |
|---|
| @scope (.card) { ... } |
| @scope (.card) to (.reviews) { ... } |
| :scope { ... } |
| @scope (.card) { :scope > p { ... } } |
| <style>@scope { ... }</style> |
When to reach for @scope
Common real-world scoping jobs and the root and limit that solve them. Try each one in the tool above.
| Scenario | Scope root |
|---|---|
| Contain a component's styles so they don't leak out | .card |
| Protect a nested, unrelated component from parent styles | .article |
| Style a post but skip pulled-out quotes | .post |
| Theme a widget and its contents in one block | .menu |
| Style a form but exclude a third-party payment iframe wrapper | .checkout |
Frequently Asked Questions
What does this CSS @scope playground do?
ScopeLab is a live editor for the CSS @scope rule. You edit HTML in one pane and CSS in another, and the tool renders the result in a sandboxed preview while drawing an outline around every element that is inside your scope root and, when you set a scope limit, marking the boundary where the scope stops.
It exists because @scope is easy to read about but hard to picture. Seeing the highlighted zone shrink the moment you add a scope limit builds the mental model faster than any static code snippet.
What is the difference between the scope root and the scope limit?
| Scope root — @scope (.card) | Scope limit — to (.reviews) | |
|---|---|---|
| Sets | The upper boundary: where the scope begins | The lower boundary: where the scope stops |
| Includes | The matched element and its descendants | Nothing — the matched element and below are cut out |
| Required? | Yes | No, it is optional |
| Creates | A normal scope | A donut scope with a hole in the middle |
How is CSS @scope different from Shadow DOM?
Both isolate styles, but at very different costs. Shadow DOM creates a hard boundary: styles cannot cross it in either direction, inherited properties are cut off, and you usually need a custom element or a framework to set it up.
@scope is a pure CSS feature. It scopes a set of rules to a subtree without a new DOM boundary, so inheritance still flows through and outside styles still reach in unless you override them. Reach for @scope when you want to contain a component's own rules; reach for Shadow DOM when you need full encapsulation of a reusable widget.
How do I stop @scope styles from leaking into a nested component?
Add a scope limit with the to keyword. The limit selector, and everything inside it, is excluded from the scope. This is the donut pattern:
/* Style the card, but never touch the nested widget */
@scope (.card) to (.reviews) {
p { color: #7c3aed; }
}In the playground, turn on Highlight scope boundary and the .reviews element is outlined in red to show exactly where the scope ends.
Does @scope change selector specificity?
The @scope rule itself adds no specificity. A selector like p inside @scope keeps the specificity of p (0,0,1). The :scope pseudo-class, however, counts as a pseudo-class, so it adds (0,1,0) like any class would.
Proximity is the real behavior change: when two scoped rules match the same element with equal specificity, the one whose scope root is closest to the element in the DOM wins. That tie-breaker runs before source order, which surprises people. The CSS Specificity Calculator is useful for sanity-checking the numbers.
Is my HTML and CSS sent to a server?
No. Everything runs in your browser. Your markup and styles are rendered into a sandboxed iframe locally, nothing is uploaded, and there is no account or API key. You can disconnect from the network and the playground still works.
Is CSS @scope safe to use in production?
Yes. @scope reached Baseline in December 2025, meaning Chrome, Edge, Safari, and Firefox all ship it in their stable channels. For projects that still target older browsers, treat scoped styling as a progressive enhancement or keep a class-based fallback, since there is no polyfill that fully reproduces the scoping semantics.