Editor’s Draft, 28 April 2026
More details about this documentCopyright © 2026 World Wide Web Consortium. W3C® liability, trademark and permissive document license rules apply.
This CSS module describes how to collate style rules and assign values to all properties on all elements. By way of cascading and inheritance, values are propagated for all properties on all elements.
New in this level is § 3.5 Scoping Styles: the @scope rule.
CSS is a language for describing the rendering of structured documents (such as HTML and XML) on screen, on paper, etc.This is a public copy of the editors’ draft. It is provided for discussion only and may change at any moment. Its publication here does not imply endorsement of its contents by W3C. Don’t cite this document other than as work in progress.
Please send feedback by filing issues in GitHub (preferred), including the spec code “css-cascade” in the title, like this: “[css-cascade] …summary of comment…”. All issues and comments are archived. Alternately, feedback can be sent to the (archived) public mailing list www-style@w3.org.
This document is governed by the 18 August 2025 W3C Process Document.
This is a diff spec over CSS Cascading and Inheritance Level 5. It is currently an Exploratory Working Draft: if you are implementing anything, please use Level 5 as a reference. We will merge the Level 5 text into this draft once it reaches CR.
The @import rule allows users to import style rules from other style sheets. If an @import rule refers to a valid stylesheet, user agents must treat the contents of the stylesheet as if they were written in place of the @import rule, with two exceptions:
If a feature (such as the @namespace rule) explicitly defines that it only applies to a particular stylesheet, and not any imported ones, then it doesn’t apply to the imported stylesheet.
If a feature relies on the relative ordering of two or more constructs in a stylesheet (such as the requirement that @namespace rules must not have any other rules other than @import preceding it), it only applies between constructs in the same stylesheet.
For example, declarations in style rules from imported stylesheets interact with the cascade as if they were written literally into the stylesheet at the point of the @import.
Any @import rules must precede all other valid at-rules and style rules in a style sheet (ignoring @charset, @supports-condition, and @layer statement rules) and must not have any other valid at-rules or style rules between it and previous @import rules, or else the @import rule is invalid. The syntax of @import is:
@import [ <url> | <string> ] [[ layer | layer( <layer-name> ) ] || [ scope | scope( <scope-start> | <scope-boundaries> ) ] || <supports-import-condition>]? <media-import-condition> ; <supports-import-condition> = supports( [ <supports-condition> | <declaration> ] ) <media-import-condition> = <media-query-list>where:
and optionally:
the layer keyword or layer() function, which assigns the contents of the style sheet into its own anonymous cascade layer or into the named cascade layer.
The layer is added to the layer order even if the import fails to load the stylesheet, but is subject to any import conditions (just as if declared by an @layer rule wrapped in the appropriate conditional group rules).
the scope keyword or scope() function, which scopes the style rules within the stylesheet, using the scoping roots and scoping limits as described by § 3.5.4 Identifying Scoping Roots and Limits.
Note: The scope keyword behaves like a @scope rule with an empty prelude, scoping the imported rules to the parent element of the owner node of the stylesheet containing the @import rule.
Note: While the style rules within the imported stylesheet become scoped, they do not become nested. In particular, top-level selectors are not re-interpreted as relative selectors, and the & pseudo-class maintains its non-nested behavior.
the import conditions, <supports-import-condition> and <media-import-condition>, which state the conditions under which the @import rule applies.
If a <string> is provided, it must be interpreted as a <url> with the same value.
Import conditions allow the import to be media– or feature-support–dependent. In the absence of any import conditions, the import is unconditional. (Specifying all for the <media-query-list> has the same effect.) If the import conditions do not match, the rules in the imported stylesheet do not apply, exactly as if the imported stylesheet were wrapped in @media and/or @supports blocks with the given conditions.
User agents may therefore avoid fetching a conditional import as long as the import conditions do not match. Additionally, if a <supports-condition> blocks the application of the imported style sheet, the UA must not fetch the style sheet (unless it is loaded through some other link) and must return null for the import rule’s CSSImportRule.styleSheet value (even if it is loaded through some other link).
The import conditions are given by <media-query-list>, which is parsed and interpreted as a media query list, and <supports-condition>, is parsed and interpreted as a supports query. If a <declaration> is given in place of a <supports-condition>, it must be interpreted as a <supports-decl> (i.e. the extra set of parentheses is implied) and treated as a <supports-condition>.
The evaluation and full syntax of the import conditions are defined by the Media Queries [MEDIAQ] and CSS Conditional Rules [CSS-CONDITIONAL-3] specifications.
When the same style sheet is imported or linked to a document in multiple places, user agents must process (or act as though they do) each link as though the link were to an independent style sheet.
Note: This does not place any requirements on resource fetching, only how the style sheet is reflected in the CSSOM and used in specs such as this one. Assuming appropriate caching, it is perfectly appropriate for a UA to fetch a style sheet only once, even though it’s linked or imported multiple times.
The cascade origin of an imported style sheet is the cascade origin of the style sheet that imported it.
The environment encoding of an imported style sheet is the encoding of the style sheet that imported it. [css-syntax-3]
The processing of imported style sheets depends on the actual type of the linked resource:
If the resource does not have Content-Type metadata, the type is treated as text/css.
If the host document is in quirks mode, and the host document’s origin is same origin with the linked resource response’s URL’s origin, the type is treated as text/css.
Otherwise, the type is determined from its Content-Type metadata.
If the linked resource’s type is text/css, it must be interpreted as a CSS style sheet. Otherwise, it must be interpreted as a network error.
The cascade takes an unordered list of declared values for a given property on a given element, sorts them by their declaration’s precedence as determined below, and outputs a single cascaded value.
The cascade sorts declarations according to the following criteria, in descending order of precedence:
Origin and Importance The origin of a declaration is based on where it comes from and its importance is whether or not it is declared with !important (see below). The precedence of the various origins is, in descending order:Declarations from origins earlier in this list win over declarations from later origins.
Context A document language can provide for blending declarations sourced from different encapsulation contexts, such as the nested tree contexts of shadow trees in the [DOM].When comparing two declarations that are sourced from different encapsulation contexts, then for normal rules the declaration from the outer context wins, and for important rules the declaration from the inner context wins. For this purpose, [DOM] tree contexts are considered to be nested in shadow-including tree order.
Note: This effectively means that normal declarations belonging to an encapsulation context can set defaults that are easily overridden by the outer context, while important declarations belonging to an encapsulation context can enforce requirements that cannot be overridden by the outer context.
The Style Attribute Separately for normal and important declarations, declarations that are attached directly to an element (such as the contents of a style attribute) rather than indirectly mapped by means of a style rule selector take precedence over declarations the same importance that are mapped via style rule. Layers Declarations within each origin and context can be explicitly assigned to a cascade layer. For the purpose of this step, any declaration not assigned to an explicit layer is added to an implicit final layer.Cascade layers (like declarations) are sorted by order of appearance, see § 3.4.1 Layer Ordering. When comparing declarations that belong to different layers, then for normal rules the declaration whose cascade layer is latest in the layer order wins, and for important rules the declaration whose cascade layer is earliest wins.
Note: This follows the same logic used for precedence of normal and important origins, thus the !important flag maintains the same “override” purpose in both settings.
Specificity The Selectors module [SELECT] describes how to compute the specificity of a selector.When comparing declarations from two style rules, the declaration belonging to the style rule with the highest specificity wins.
Scope Proximity When comparing declarations that appear in style rules with different scoping roots, then the declaration with the fewest generational or sibling-element hops between the scoping root and the scoped style rule subject wins. For this purpose, style rules without a scoping root are considered to have infinite proximity hops. Order of Appearance The last declaration in document order wins. For this purpose:The output of the cascade is a (potentially empty) sorted list of declared values for each property on each element.
CSS Cascading 5 § 6.2 Cascading Origins
cascade origin
CSS Cascading 5 § 6.3 Important Declarations: the !important annotation
important normal
CSS Cascading 5 § 6.4 Cascade Layers
CSS Cascading 5 § 6.4.3 Layer Ordering
A scope is a subtree or fragment of a document, which can be used by selectors for more targeted matching. A scope is formed by determining:
The scoping root node, which acts as the upper bound of the scope, and optionally:
The scoping limit elements, which act as the lower bounds.
An element is in scope if:
It is an inclusive descendant of the scoping root, and
It is not an inclusive descendant of a scoping limit.
Note: In contrast to Shadow Encapsulation, which describes a persistent one-to-one relationship in the DOM between a shadow host and its nested shadow tree, multiple overlapping scopes can be defined in relation to the same elements.
Scoped styles are described in CSS using the @scope block at-rule, which declares a scoping root and optional scoping limits associated with a set of style rules.
The img selector will only match image tags that are in a DOM fragment starting with any .media-object, and including all descendants up to any intervening children of the .content class.
Should scoping limits be added to the definition of scoped selectors?
The @scope at-rule has three primary effects on the style rules it contains:
The style rules in an @scope <rule-list> are scoped style rules.
The :scope selector is defined to match the @scope rule’s scoping root, including the featureless shadow host when that host is the scoping root.
The & selector is defined to behave as :where(:scope).
The cascade prioritizes declarations with a more proximate scoping root, regardless of specificity or order of appearance by applying scope proximity between the scoping root and the subject of each scoped style rule.
Note: Unlike Nesting, selectors within an @scope rule do not acquire the specificity of any parent selector(s) in the @scope prelude.
The additional specificity of the #hero selector is not applied to the specificity of the scoped selector. However, since one img selector is scoped, that selector is weighted more strongly in the cascade with the application of scope proximity.
Those custom scope attributes are then appended to every single selector in CSS:
p[data-scope~='main-component'] { color: red; } p[data-scope~='sub-component'] { color: blue; } /* both sections are part of the outer scope */ section[data-scope~='main-component'] { background: snow; } /* the inner section is also part of the inner scope */ section[data-scope~='sub-component'] { color: ghostwhite; }Using the @scope rule, authors and tools can replicate similar behavior with the unique attribute or class applied only to the scoping roots:
<section data-scope="main-component"> <p>...<p> <section data-scope="sub-component"> <p>...<p> </section> </section>Then the class or attribute can be used for establishing both upper and lower boundaries. Elements matched by a lower boundary selector are excluded from the resulting scope, which allows authors to create non-overlapping scopes by default:
@scope ([data-scope='main-component']) to ([data-scope]) { p { color: red; } /* only the outer section is part of the outer scope */ section { background: snow; } } @scope ([data-scope='sub-component']) to ([data-scope]) { p { color: blue; } /* the inner section is only part of the inner scope */ section { color: ghostwhite; } }However, authors can use the child combinator and universal selector to create scope boundaries that overlap, such that the inner scope root is part of both scopes:
@scope ([data-scope='main-component']) to ([data-scope] > *) { p { color: red; } /* both sections are part of the outer scope */ section { background: snow; } }The syntax of the @scope rule is:
@scope <scope-boundaries>? { <block-contents> }with <scope-boundaries> defined as:
<scope-boundaries> = [ [ ( <scope-start> ) ]? [ to ( <scope-end> ) ]? ]!and where:
<scope-start> is a <selector-list> selector used to identify the scoping root(s).
<scope-end> is a <selector-list> selector used to identify any scoping limits.
the qualified rules within <block-contents>, as well as any nested declarations rules produced by scoped declarations, represents the scoped style rules.
Pseudo-elements cannot be scoping roots or scoping limits; they are invalid both within <scope-start> and <scope-end>.
Scoped style rules differ from non-scoped rules in the following ways:
Their selectors can only match elements that are in scope. (This only applies to the subject; the rest of the selector can match unrestricted.)
They accept a <relative-selector-list> as their prelude (rather than just a <selector-list>). Such relative selectors are relative to :scope.
Any selector in the <relative-selector-list> that does not start with a combinator but does contain the nesting selector or the :scope selector, is interpreted as a non-relative selector (but the subject must still be in scope to match).
Authors can adjust the implied relationship by adding an explicit combinator:
@scope (#my-component) { > p { color: green; } :scope > p { color: green; } }Authors can also target or explicitly position the scoping root in a selector by including either :scope or & in a given selector:
@scope (#my-component) { :scope { border: thin solid; } & { border: thin solid; } main :scope p { color: green; } main & p { color: green; } }Both the :scope and & selectors match the scope root, but with different specificity: :scope has as specificity of (0,1,0), whereas & has a specificity of 0.
A @scope rule produces one or more scopes as follows:
Finding the scoping root(s)For each element matched by <scope-start>, create a scope using that element as the scoping root. If no <scope-start> is specified, the scoping root is the parent element of the owner node of the stylesheet where the @scope rule is defined. (If no such element exists and the containing node tree is a shadow tree, then the scoping root is the shadow host. Otherwise, the scoping root is the root of the containing node tree.) Any :scope or & selectors in <scope-start> are interpreted as defined for its outer context.
Finding any scoping limitsFor each scope created by a scoping root, its scoping limits are set to all elements that are descendants of the scoping root and that match <scope-end>, interpreting :scope and & exactly as in scoped style rules.
That would be equivalent to:
<div id="foo"> <style> @scope (#foo) { p { color: red; } } </style> <p>this is red</p> </div> <p>not red</p>Scoping limits can also reference elements outside their scoping root by using :scope. For example:
/* .content is only a limit when the :scope is inside .sidebar */ @scope (.media-object) to (.sidebar :scope .content) { ... }@scope rules can be nested. In this case, just as with the nested style rules, the prelude selectors of the inner @scope (those defining its scope) are scoped by the selectors of the outer one.
Note: The resulting scope for further nested scoped style rules is practically constrained by both the outer and inner @scope rules, but the scoping root is defined by the innermost @scope. Since scope proximity is measured between a scoped style rule subject and scoping root, only the innermost @scope matters for determining scope proximity of nested @scope rules.
Should the scope proximity calculation be impacted by nesting scopes? [Issue #10795]
is equivalent to:
@scope (.parent-scope > .child-scope) to (.parent-scope > .child-scope .limit) { .parent-scope > .child-scope .content { color: red; } }Global name-defining at-rules such as @keyframes or @font-face or @layer that are defined inside @scope are valid, but are not scoped or otherwise affected by the enclosing @scope rule. However, any style rules contained by such rules (e.g. within @layer) are scoped.
Declarations may be used directly with the body of a @scope rule. Contiguous runs of declarations are wrapped in nested declarations rules, which match the scoping root with zero specificity.
is equivalent to:
@scope (.foo) { :where(:scope) { border: 1px solid black; } }Just like for style rules, declarations and child rules may be mixed within @scope.
CSS Cascading 5 § 6.4 Cascade Layers
The CSSScopeRule interface represents the @scope rule:
[Exposed=Window] interface CSSScopeRule : CSSGroupingRule { readonly attribute CSSOMString? start; readonly attribute CSSOMString? end; }; start of type CSSOMString The start attribute returns the result of serializing the <scope-start> of the rule (without the enclosing parentheses), or null if there is no <scope-start>. end of type CSSOMString The end attribute returns the result of serializing the <scope-end> of the rule (without the enclosing parentheses), or null if there is no <scope-end>.This appendix is informative.
Significant changes since the 21 March 2023 Working Draft include:
Added the @import scope() syntax, and the ability to specificy layer(), scope(), and supports() in any order. (Issue 7348)
Defined & to behave like :where(:scope). (Issue 9740)
Allowed declarations directly within @scope. (Issue 10389)
The :scope selector can match the featureless shadow host when that host is the scoping root element. (Issue 9025)
<scope-start> and <scope-end> selectors are unforgiving. (Issue 10042)
A @scope rule without <scope-start> scopes to the shadow host instead of the shadow root. (Issue 9178)
Clarified that scope proximity is a single measurement of the steps between a single scoping root and scoped style rule subject (Issue 10795 has been opened to discuss this futher).
Removed strong scope proximity. (Issue 6790)
Removed the scoped descendant combinator (deferred). (Issue 8628)
Added the CSSScopeRule interface. (Issue 8626)
Significant changes since the 21 December 2021 First Public Working Draft include:
Clarified @scope effects on nested :scope and & selectors. (Issue 8377)
Removed @scope prelude from specificity calculation. (Issue 8500)
Specified how name-defining at-rules behave in @scope. (Issue 6895)
Added implicit scopes by making <scope-start> optional. (Issue 6606)
Disallowed pseudo-elements in the @scope prelude. (Issue 7382)
Removed selector scoping notation. (Issue 7709)
Scoping limit elements are excluded from the resulting scope. (Issue 6577)
The following features have been added since Level 5:
The definition of a scope, as described by a combination of <scope-start> and <scope-end> selectors.
The in-scope (:in()) pseudo-class for selecting with lower-boundaries
The @scope rule for creating scoped stylesheets
The definition of scope proximity in the cascade
The following features have been added since Level 4:
Added cascade layers to the cascade sort criteria (and defined style attributes as a distinct step of the cascade sort criteria so that they interact appropriately).
Introduced the @layer rule for defining cascade layers.
Added layer/layer() option to @import definition.
Introduced the revert-layer keyword for rolling back values to previous layers.
The following features have been added since Level 3:
Introduced revert keyword, for rolling back the cascade.
Introduced supports() syntax for supports-conditional @import rules.
Added encapsulation context to the cascade sort criteria to accommodate Shadow DOM. [DOM]
Defined the property two aliasing mechanisms CSS uses to support legacy syntaxes. See CSS Cascading 4 § 3.1 Property Aliasing.
The following features have been added since Level 2:
David Baron, Tantek Çelik, Keith Grant, Giuseppe Gurgone, Theresa O’Connor, Florian Rivoal, Noam Rosenthal, Simon Sapin, Jen Simmons, Nicole Sullivan, Lea Verou, and Boris Zbarsky contributed to this specification.
User preferences and UA defaults expressed via application of style rules are exposed by the cascade process, and can be inferred from the computed styles they apply to a document.
The cascade process does not distinguish between same-origin and cross-origin stylesheets, enabling the content of cross-origin stylesheets to be inferred from the computed styles they apply to a document.
The @import rule does not apply the CORS protocol to loading cross-origin stylesheets, instead allowing them to be freely imported and applied.
The @import rule assumes that resources without Content-Type metadata (or any same-origin file if the host document is in quirks mode) are text/css, potentially allowing arbitrary files to be imported into the page and interpreted as CSS, potentially allowing sensitive data to be inferred from the computed styles they apply to a document.
Conformance requirements are expressed with a combination of descriptive assertions and RFC 2119 terminology. The key words “MUST”, “MUST NOT”, “REQUIRED”, “SHALL”, “SHALL NOT”, “SHOULD”, “SHOULD NOT”, “RECOMMENDED”, “MAY”, and “OPTIONAL” in the normative parts of this document are to be interpreted as described in RFC 2119. However, for readability, these words do not appear in all uppercase letters in this specification.
All of the text of this specification is normative except sections explicitly marked as non-normative, examples, and notes. [RFC2119]
Examples in this specification are introduced with the words “for example” or are set apart from the normative text with class="example", like this:
Informative notes begin with the word “Note” and are set apart from the normative text with class="note", like this:
Note, this is an informative note.
Advisements are normative sections styled to evoke special attention and are set apart from other normative text with <strong class="advisement">, like this: UAs MUST provide an accessible alternative.
TestsTests relating to the content of this specification may be documented in “Tests” blocks like this one. Any such block is non-normative.
Conformance to this specification is defined for three conformance classes:
style sheet A CSS style sheet. renderer A UA that interprets the semantics of a style sheet and renders documents that use them. authoring tool A UA that writes a style sheet.A style sheet is conformant to this specification if all of its statements that use syntax defined in this module are valid according to the generic CSS grammar and the individual grammars of each feature defined in this module.
A renderer is conformant to this specification if, in addition to interpreting the style sheet as defined by the appropriate specifications, it supports all the features defined by this specification by parsing them correctly and rendering the document accordingly. However, the inability of a UA to correctly render a document due to limitations of the device does not make the UA non-conformant. (For example, a UA is not required to render color on a monochrome monitor.)
An authoring tool is conformant to this specification if it writes style sheets that are syntactically correct according to the generic CSS grammar and the individual grammars of each feature in this module, and meet all other conformance requirements of style sheets as described in this module.
So that authors can exploit the forward-compatible parsing rules to assign fallback values, CSS renderers must treat as invalid (and ignore as appropriate) any at-rules, properties, property values, keywords, and other syntactic constructs for which they have no usable level of support. In particular, user agents must not selectively ignore unsupported component values and honor supported values in a single multi-value property declaration: if any value is considered invalid (as unsupported values must be), CSS requires that the entire declaration be ignored.
To avoid clashes with future stable CSS features, the CSSWG recommends following best practices for the implementation of unstable features and proprietary extensions to CSS.
Once a specification reaches the Candidate Recommendation stage, non-experimental implementations are possible, and implementors should release an unprefixed implementation of any CR-level feature they can demonstrate to be correctly implemented according to spec.
To establish and maintain the interoperability of CSS across implementations, the CSS Working Group requests that non-experimental CSS renderers submit an implementation report (and, if necessary, the testcases used for that implementation report) to the W3C before releasing an unprefixed implementation of any CSS features. Testcases submitted to W3C are subject to review and correction by the CSS Working Group.
Further information on submitting testcases and implementation reports can be found from on the CSS Working Group’s website at http://www.w3.org/Style/CSS/Test/. Questions should be directed to the public-css-testsuite@w3.org mailing list.
In all current engines.
In all current engines.
In all current engines.
In all current engines.
In all current engines.