container
@scope
Constrains selectors to a subtree of the DOM defined by a scope root and an optional lower boundary, without adding specificity. It provides native, donut-shaped style scoping similar to what CSS-in-JS libraries emulate.
@scope (<root-selector>) [to (<limit-selector>)] { <rules> } Common conditions / descriptors
| Descriptor | Purpose |
|---|---|
| (<root>) | Scope root — the ancestor where scope begins |
| to (<limit>) | Lower boundary — descendants at or below this are excluded |
| :scope | Refers to the scope root inside the block |
| & (nesting) | Also references the scope root and can nest normally |
Examples
@scope (.card) {
:scope { border: 1px solid #e5e7eb; }
h2 { font-weight: 600; }
} Style anything inside .card without leaking selectors globally
@scope (.article) to (.comments) {
a { text-decoration: underline; }
} Style links inside .article but NOT inside a nested .comments block
@scope (.dark) {
:scope { background: #0b0b0f; color: #f5f5f7; }
} Theme scope that opts a subtree into dark styles
@scope (nav) {
li + li { margin-inline-start: .75rem; }
} Sibling spacing scoped to nav only
Gotcha
@scope is now baseline across evergreen browsers — Chrome, Safari, and Firefox (since Firefox 128, July 2024). — feature-detect with @supports before relying on it. Scope does not increase specificity; use it to limit reach, not to win the cascade.
Related at-rules
@container
Applies rules based on the size or style of a nearest containment context rather than the viewport, enabling truly component-scoped responsiveness. Requires an ancestor that opts in via container-type.
@layer
Declares one or more cascade layers so authors can control the order in which rule groups cascade, independent of specificity. Layers declared later win over layers declared earlier, and unlayered styles win over all named layers.
@supports
Applies rules only when the browser supports the tested CSS feature, enabling progressive enhancement without JavaScript. Conditions can be combined with and, or, and not.