<pre class='metadata'>
Title: CSS Cascading and Inheritance Module Level 6
Shortname: css-cascade
Level: 6
Status: ED
Prepare for TR: no
Work Status: Revising
Group: csswg
ED: https://drafts.csswg.org/css-cascade-6/
TR: https://www.w3.org/TR/css-cascade-6/
Previous Version: https://www.w3.org/TR/2021/WD-css-cascade-6-20211221/
Editor: Elika J. Etemad / fantasai, Apple, http://fantasai.inkedblade.net/contact, w3cid 35400
Editor: Miriam E. Suzanne, Invited Expert, http://miriamsuzanne.com/contact, w3cid 117151
Editor: Tab Atkins Jr., Google, http://xanthir.com/contact/, w3cid 42199
Abstract: 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.
Abstract:
Abstract: New in this level is [[#scoped-styles]].
Ignored Terms: auto, flex items, <supports-condition>
Informative Classes: ex
</pre>

<pre class=link-defaults>
spec:dom; type:dfn;
	text:shadow tree
	for:tree; text:root
	text:shadow root; for:/
spec:dom; type:dfn; text:parent element
spec:css-color-4; type:property; text:color
spec:css-values-3; type: value; text:ex
spec:css-conditional-3; type:at-rule; text:@media
spec:mediaqueries-4; type:type; for:@media; text:all
spec:mediaqueries-4; type:type; text:<media-query>
spec:selectors-4; type:dfn; text:subject
spec:selectors-4; type:dfn; text:selector
spec:selectors-4; type:dfn; text:combinator
spec:html; type:element; text:style
spec:css-scoping-1; type:dfn; text:shadow host
spec:css-display-4; type:property; text:display
</pre>

<pre class=ignored-specs>
spec:mediaqueries-5
spec:css-values-4
spec:css-fonts-4
</pre>

<h2 id="intro" oldids='filtering,fragments,stages-examples,actual,used,computed,cascaded,declared,specified,value-stages,all-shorthand,aliasing,shorthand,defaulting,initial-values,inheriting,defaulting-keywords,initial,inherit,inherit-initial,default,layer-empty'>
Introduction and Missing Sections</h2>

	Issue: This is a diff spec over <a href="https://www.w3.org/TR/css-cascade-5/">CSS Cascading and Inheritance Level 5</a>.
	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.

<!--
 ███████  ████ ██     ██ ████████   ███████  ████████  ████████
██     ██  ██  ███   ███ ██     ██ ██     ██ ██     ██    ██
██ ███ ██  ██  ████ ████ ██     ██ ██     ██ ██     ██    ██
██ ███ ██  ██  ██ ███ ██ ████████  ██     ██ ████████     ██
██ █████   ██  ██     ██ ██        ██     ██ ██   ██      ██
██         ██  ██     ██ ██        ██     ██ ██    ██     ██
 ███████  ████ ██     ██ ██         ███████  ██     ██    ██
-->

<h2 id="at-import">
Importing Style Sheets: the ''@import'' rule</h2>

	The <dfn>@import</dfn> 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)
		<em>explicitly</em> 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.

	<p class='example'>
		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 <a href="#layer-empty"><css>@layer</css> statement</a> 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:

<pre class='prod'>
		@import [ <<url>> | <<string>> ]
		        [[ layer | layer( <<layer-name>> ) ]
		         || [ scope | scope( <<scope-start>> | <<scope-boundaries>> ) ]
		         || <<supports-import-condition>>]?
		        <<media-import-condition>> ;

		<dfn export>&lt;supports-import-condition></dfn> = supports( [ <<supports-condition>> | <<declaration>> ] )
		<dfn export>&lt;media-import-condition></dfn> = <<media-query-list>></pre>

	where:

	* the <<url>> or <<string>>
		gives the URL of the style sheet to be imported.

	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-ordering|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 [[#scope-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 style rule|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.

	<div class="example">
		The following <a href="#conditional-import">conditional <css>@import</css> rule</a>
		only loads the style sheet when the UA
		<a href="https://www.w3.org/TR/css-conditional-3/#support-definition">supports</a> ''display: flex'',
		and only applies the style sheet on a <a href="https://www.w3.org/TR/CSS2/media.html#media-types">handheld</a> device
		with a <a href="https://www.w3.org/TR/mediaqueries-4/#width">maximum viewport width</a> of 400px.

		<pre>@import url("narrow.css") supports(display: flex) handheld and (max-width: 400px);</pre>
	</div>

	<div class="example">
		The following layer imports load the style sheets into
		the ''framework.component'' layer, and an un-named layer, respectively:

		<pre>
		@import url("tabs.css") layer(framework.component);
		@import url("override.css") layer;
		</pre>
	</div>

	<div class="example">
		The following imports a stylesheet, and scopes the style rules
		to elements matching <code>.card</code>.

		<pre>
		@import url("card.css") scope(.card);
		</pre>
	</div>

	If a <<string>> is provided,
	it must be interpreted as a <<url>> with the same value.

	<div class="example">
		The following lines are equivalent in meaning
		and illustrate both ''@import'' syntaxes
		(one with ''url()'' and one with a bare string):

		<pre class='lang-css'>
		@import "mystyle.css";
		@import url("mystyle.css");
		</pre>
	</div>

<h3 id=conditional-import>
Conditional ''@import'' Rules</h3>

	<dfn export>Import conditions</dfn> allow the import to be media&ndash; or feature-support&ndash;dependent.
	In the absence of any <a>import conditions</a>, the import is unconditional.
	(Specifying ''@media/all'' for the <<media-query-list>> has the same effect.)
	If the <a>import conditions</a> 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.

	<div class=example>
		The following rules illustrate how ''@import'' rules can be made media-dependent:

		<pre class='lang-css'>
		@import url("fineprint.css") print;
		@import url("bluish.css") projection, tv;
		@import url("narrow.css") handheld and (max-width: 400px);
		</pre>
	</div>

	User agents may therefore avoid fetching a conditional import
	as long as the <a>import conditions</a> do not match.
	Additionally, if a <<supports-condition>> blocks the application of the imported style sheet,
	the UA <em>must not</em> fetch the style sheet (unless it is loaded through some other link)
	and <em>must</em> return null for the import rule's CSSImportRule.styleSheet value
	(even if it is loaded through some other link).

	<div class="example">
		The following rule illustrates how an author can provide fallback rules for legacy user agents
		without impacting network performance on newer user agents:

		<pre class='lang-css'>
		@import url("fallback-layout.css") supports(not (display: flex));
		@supports (display: flex) {
		  ...
		}
		</pre>
	</div>

	The [=import conditions=] are given by
	<<media-query-list>>, which is parsed and interpreted as a <a>media query list</a>,
	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>>.

	<div class="example">
		For example, the following two lines are equivalent:
		<pre class='lang-css'>
		@import "mystyle.css" supports(display: flex);
		@import "mystyle.css" supports((display: flex));
		</pre>
	</div>

	The evaluation and full syntax of the <a>import conditions</a>
	are defined by the <a href="https://www.w3.org/TR/mediaqueries/">Media Queries</a> [[!MEDIAQ]]
	and <a href="https://www.w3.org/TR/css-conditional/">CSS Conditional Rules</a> [[!CSS-CONDITIONAL-3]] specifications.

<h3 id=import-processing>
Processing Stylesheet Imports</h3>

	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 <a>environment encoding</a> of an imported style sheet is the encoding of the style sheet that imported it. [[css-syntax-3]]

<h3 id='content-type'>
Content-Type of CSS Style Sheets</h3>

	The processing of imported style sheets depends on the actual type of the linked resource:

	* If the resource does not have <l spec=html>[=Content-Type metadata=]</l>,
		the type is treated as <code>text/css</code>.
	* If the host document is in [=quirks mode=],
		and the host document's origin is [=same origin=]
		with the linked resource [=/response's=] [=response/URL's=] origin,
		the type is treated as <code>text/css</code>.
	* Otherwise, the type is determined from its <l spec=html>[=Content-Type metadata=]</l>.

	If the linked resource's type is <code>text/css</code>,
	it must be interpreted as a CSS style sheet.
	Otherwise, it must be interpreted as a network error.

<!--
 ██████     ███     ██████   ██████     ███    ████████  ████████
██    ██   ██ ██   ██    ██ ██    ██   ██ ██   ██     ██ ██
██        ██   ██  ██       ██        ██   ██  ██     ██ ██
██       ██     ██  ██████  ██       ██     ██ ██     ██ ██████
██       █████████       ██ ██       █████████ ██     ██ ██
██    ██ ██     ██ ██    ██ ██    ██ ██     ██ ██     ██ ██
 ██████  ██     ██  ██████   ██████  ██     ██ ████████  ████████
-->

<h2 id='cascading'>
Cascading</h2>

	The <dfn export>cascade</dfn>
	takes an unordered list of <a>declared values</a>
	for a given property on a given element,
	sorts them by their [=declaration’s=] precedence as determined below,
	and outputs a single <a>cascaded value</a>.

<h3 id="cascade-sort">
Cascade Sorting Order</h3>

	The cascade sorts [=declarations=] according to the following criteria,
	in descending order of precedence:

	<dl>
		<dt id='cascade-origin'>Origin and Importance
		<dd>
			The <a>origin</a> of a [=declaration=] is based on where it comes from
			and its <a lt="important">importance</a> is
			whether or not it is declared with ''!important''
			(see [[#importance|below]]).
			The precedence of the various <a>origins</a> is, in descending order:

			<ol>
				<li>Transition declarations [[!css-transitions-1]]
				<li>[=Important=] [=user-agent origin|user agent=] declarations
				<li>[=Important=] [=user origin|user=] declarations
				<li>[=Important=] [=author origin|author=] declarations
				<li>Animation declarations [[!css-animations-1]]
				<li>[=Normal=] [=author origin|author=] declarations
				<li>[=Normal=] [=user origin|user=] declarations
				<li>[=Normal=] [=user-agent origin|user agent=] declarations
			</ol>

			Declarations from <a>origins</a> earlier in this list win over declarations from later <a>origins</a>.

		<dt id='cascade-context'>Context
		<dd>
			A document language can provide for blending [=declarations=] sourced
			from different <dfn local-lt="context">encapsulation contexts</dfn>,
			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.

		<dt id='style-attr'>The Style Attribute
		<dd>
			Separately for [=normal=] and [=important=] [=declarations=],
			declarations that are attached directly to an element
			(such as the <a href="https://www.w3.org/TR/css-style-attr/#interpret">contents of a style attribute</a>)
			rather than indirectly mapped by means of a style rule selector
			take precedence over declarations the same [=importance=]
			that are mapped via style rule.

		<dt id='cascade-layering'>Layers
		<dd>
			[=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 [[#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.

		<dt id='cascade-specificity'>Specificity
		<dd>
			The <a href="https://www.w3.org/TR/selectors/#specificity">Selectors module</a> [[!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.

		<dt id='cascade-proximity'><dfn>Scope Proximity</dfn>
		<dd>
			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.

		<dt id='cascade-order'>Order of Appearance
		<dd>
			The last declaration in document order wins.
			For this purpose:

			<ul>
				<li>Style sheets are ordered as in <a href="https://drafts.csswg.org/cssom/#documentorshadowroot-final-css-style-sheets">final CSS style sheets</a>.
				<li>Declarations from <a at-rule lt="@import">imported style sheets</a>
					are ordered as if their style sheets were substituted in place of the ''@import'' rule.
				<li>Declarations from style sheets independently linked by the originating document
					are treated as if they were concatenated in linking order,
					as determined by the host document language.
				<li>Declarations from style attributes
					are ordered according to the document order of the element the style attribute appears on,
					and are all placed after any style sheets.
					[[!CSSSTYLEATTR]]
			</ul>
	</dl>

	The <dfn export>output of the cascade</dfn>
	is a (potentially empty) sorted list of <a>declared values</a> for each property on each element.


<h3 id='cascading-origins'>
Cascading Origins</h3>

	Issue: [[css-cascade-5#cascading-origins]]

	<dfn id=origin export local-lt="origin">cascade origin</dfn>

<h3 id='importance'>
Important Declarations: the ''!important'' annotation</h3>

	Issue: [[css-cascade-5#importance]]

	<dfn export local-lt="importance">important</dfn>
	<dfn>normal</dfn>

<h3 id='layering'>
Cascade Layers</h3>

	Issue: [[css-cascade-5#layering]]

<h4 id="layer-ordering">
Layer Ordering</h4>

	Issue: [[css-cascade-5#layer-ordering]]


<!--
 ██████   ██████   ███████  ████████  ████ ██    ██  ██████
██    ██ ██    ██ ██     ██ ██     ██  ██  ███   ██ ██    ██
██       ██       ██     ██ ██     ██  ██  ████  ██ ██
 ██████  ██       ██     ██ ████████   ██  ██ ██ ██ ██   ████
      ██ ██       ██     ██ ██         ██  ██  ████ ██    ██
██    ██ ██    ██ ██     ██ ██         ██  ██   ███ ██    ██
 ██████   ██████   ███████  ██        ████ ██    ██  ██████
-->

<h3 id='scoped-styles' oldids="scope-atrule">
Scoping Styles: the ''@scope'' rule</h3>

	A <dfn>scope</dfn> 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 <dfn>scoping limit</dfn> elements,
		which act as the lower bounds.

	An element is <dfn>in scope</dfn> 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 [[CSS-SCOPING-1#shadow-dom|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 <dfn>@scope</dfn> [=block at-rule=],
	which declares a [=scoping root=] and optional [=scoping limits=]
	associated with a set of [=style rules=].

	<div class=example>
		For example,
		an author might have wide-reaching color-scheme scopes,
		which overlap more narrowly-scoped design patterns
		such as a media object.
		The selectors in the ''@scope'' rule
		establish [=scoping root=] and optional [=scoping limit=] elements,
		while the nested selectors only match elements
		that are [=in scope|in a resulting scope=]:

		<pre highlight=css>
		@scope (.light-scheme) {
		  /* Only match links inside a light-scheme */
		  a { color: darkmagenta; }
		}

		@scope (.dark-scheme) {
		  /* Only match links inside a dark-scheme */
		  a { color: plum; }
		}

		@scope (.media-object) {
		  /* Only match author images inside a media-object */
		  .author-image { border-radius: 50%; }
		}
		</pre>
	</div>

	<div class=example>
		By providing [=scoping limits=],
		an author can limit matching more deeply nested descendants.
		For example:

		<pre highlight=css>
		@scope (.media-object) to (.content > *) {
		  img { border-radius: 50%; }
		  .content { padding: 1em; }
		}
		</pre>

		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.
	</div>

	Issue: Should scoping limits be added to the definition of [=scoped selectors=]?


<h4 id="scope-effects">
Effects of ''@scope''</h4>

	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 <code>:where(:scope)</code>.
	* The [=cascade=] prioritizes declarations
		with a [=scope proximity|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 <a href="https://www.w3.org/TR/css-nesting/">Nesting</a>,
	selectors within an ''@scope'' rule
	do not acquire the specificity of any parent selector(s) in the ''@scope'' prelude.

	<div class=example>
		The following selectors have the same specificity (0,0,1):

		<pre highlight=css>
		@scope (#hero) {
		  img { border-radius: 50%; }
		}

		:where(#hero) img { border-radius: 50%; }
		</pre>

		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=].
	</div>

	<div class=example>
		Many existing tools implement "scoped styles"
		by applying a unique class or attribute
		to every element in a given scope
		or "single file component."
		In this example there are two scopes
		(<code>main-component</code> and <code>sub-component</code>)
		and every element is marked as part of one or both scopes
		using the <code>data-scope</code> attribute:

		<pre class=lang-html>
		&lt;section data-scope="main-component">
		  &lt;p data-scope="main-component">...&lt;p>

		  &lt;!-- sub-component root is in both scopes -->
		  &lt;section data-scope="main-component sub-component">
		    &lt;!-- children are only in the inner scope -->
		    &lt;p data-scope="sub-component">...&lt;p>
		  &lt;/section>
		&lt;/section>
		</pre>

		Those custom scope attributes are then
		appended to every single selector in CSS:

		<pre highlight=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; }
		</pre>

		Using the ''@scope'' rule,
		authors and tools can replicate similar behavior
		with the unique attribute or class
		applied only to the [=scoping roots=]:

		<pre class=lang-html>
		&lt;section data-scope="main-component">
		  &lt;p>...&lt;p>
		  &lt;section data-scope="sub-component">
		    &lt;p>...&lt;p>
		  &lt;/section>
		&lt;/section>
		</pre>

		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:

		<pre highlight=css>
		@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; }
		}
		</pre>

		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:

		<pre highlight=css>
		@scope ([data-scope='main-component']) to ([data-scope] > *) {
		  p { color: red; }

		  /* both sections are part of the outer scope */
		  section { background: snow; }
		}
		</pre>
	</div>

<h4 id="scope-syntax">
Syntax of ''@scope''</h4>

	The syntax of the ''@scope'' rule is:

	<pre class="prod def">
	@scope <<scope-boundaries>>? {
	  <<block-contents>>
	}
	</pre>

	with <<scope-boundaries>> defined as:
	<pre class="prod def">
	<dfn export>&lt;scope-boundaries></dfn> =  [ [ ( <<scope-start>> ) ]? [ to ( <<scope-end>> ) ]? ]!
	</pre>

	and where:

	* <dfn><<scope-start>></dfn> is a <<selector-list>> [=selector=]
		used to identify the [=scoping root=](s).
	* <dfn><<scope-end>></dfn> 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|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>>.

<h4 id="scoped-rules">
Scoped Style Rules</h4>

	<dfn export>Scoped style rules</dfn> 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).

	<div class="example">
		By default, selectors in a [=scoped style rule=]
		are [=relative selectors=],
		with the [=scoping root=] and [=descendant combinator=]
		implied at the start.
		The following selectors will match the same elements:

		<pre highlight=css>
		@scope (#my-component) {
		  p { color: green; }
		  :scope p { color: green; }
		}
		</pre>

		Authors can adjust the implied relationship
		by adding an explicit combinator:

		<pre highlight=css>
		@scope (#my-component) {
		  > p { color: green; }
		  :scope > p { color: green; }
		}
		</pre>

		Authors can also target or explicitly position
		the [=scoping root=] in a selector
		by including either '':scope'' or ''&'' in a given selector:

		<pre highlight=css>
		@scope (#my-component) {
		  :scope { border: thin solid; }
		  & { border: thin solid; }

		  main :scope p { color: green; }
		  main & p { color: green; }
		}
		</pre>

		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.
	</div>

<h4 id="scope-limits">
Identifying Scoping Roots and Limits</h4>

	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 limits=]
	:: For 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=].

	<div class=example>
		Authors can establish local scoping
		for <{style}> elements by leaving out the <<scope-start>> selector.
		For example:

		<pre class=lang-html>
		&lt;div>
		  &lt;style>
		    @scope {
		      p { color: red; }
		    }
		  &lt;/style>
		  &lt;p>this is red&lt;/p>
		&lt;/div>
		&lt;p>not red&lt;/p>
		</pre>

		That would be equivalent to:

		<pre class=lang-html>
		&lt;div id="foo">
		  &lt;style>
		    @scope (#foo) {
		      p { color: red; }
		    }
		  &lt;/style>
		  &lt;p>this is red&lt;/p>
		&lt;/div>
		&lt;p>not red&lt;/p>
		</pre>
	</div>

	<div class=example>
		[=Scoping limits=] can use the '':scope'' pseudo-class
		to require a specific relationship to the [=scoping root=]:

		<pre highlight=css>
		/* .content is only a limit when it is a direct child of the :scope */
		@scope (.media-object) to (:scope > .content) { ... }
		</pre>

		[=Scoping limits=] can also reference elements outside their [=scoping root=]
		by using '':scope''.
		For example:

		<pre highlight=css>
		/* .content is only a limit when the :scope is inside .sidebar */
		@scope (.media-object) to (.sidebar :scope .content) { ... }
		</pre>
	</div>

<h4 id="scope-scope">
Scope Nesting</h4>

	''@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 selectors|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 [[#scope-scope|nested @scope rules]].

Issue(10795): Should the scope proximity calculation be impacted by nesting scopes?

	<div class=example>
		When nesting ''@scope'' rules inside other ''@scope'' rules,
		or inside other selectors,
		the <<scope-start>> selector is
		[=relative selector|relative to=] the nesting context,
		while the <<scope-end>> and any [=scoped style rules=]
		are [=relative selector|relative to=] the [=scoping root=]
		For example, the following code:

		<pre highlight=css>
		@scope (.parent-scope) {
		  @scope (:scope > .child-scope) to (:scope .limit) {
		    :scope .content {
		      color: red;
		    }
		  }
		}
		</pre>

		is equivalent to:

		<pre highlight=css>
		@scope (.parent-scope > .child-scope) to (.parent-scope > .child-scope .limit) {
		  .parent-scope > .child-scope .content {
		    color: red;
		  }
		}
		</pre>
	</div>

	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 style rules|scoped=].

<h4 id="scoped-declarations">
Scoped Declarations </h4>

	[=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=].

	<div class=example>
		<pre highlight=css>
		@scope (.foo) {
		  border: 1px solid black;
		}
		</pre>

		is equivalent to:

		<pre highlight=css>
		@scope (.foo) {
		  :where(:scope) {
		    border: 1px solid black;
		  }
		}
		</pre>
	</div>

	Just like for [=style rules=],
	[=declarations=] and child [=rules=]
	may be [[css-nesting-1#mixing|mixed]]
	within ''@scope''.

<h3 id="preshint">
Precedence of Non-CSS Presentational Hints</h3>

	Issue: [[css-cascade-5#layering]]

<!--
 ██████   ██████   ██████   ███████  ██     ██
██    ██ ██    ██ ██    ██ ██     ██ ███   ███
██       ██       ██       ██     ██ ████ ████
██        ██████   ██████  ██     ██ ██ ███ ██
██             ██       ██ ██     ██ ██     ██
██    ██ ██    ██ ██    ██ ██     ██ ██     ██
 ██████   ██████   ██████   ███████  ██     ██
-->

CSSOM {#cssom}
==============


<h3 id="the-cssscoperule-interface">
The <code>CSSScopeRule</code> interface</h3>

	The {{CSSScopeRule}} interface represents the ''@scope'' rule:

	<pre class='idl' export>
	[Exposed=Window]
	interface CSSScopeRule : CSSGroupingRule {
	  readonly attribute CSSOMString? start;
	  readonly attribute CSSOMString? end;
	};
	</pre>

	<dl class='idl-attributes'>
		<dt><code>start</code> of type <code>CSSOMString</code>
		<dd>The <code>start</code> attribute
		returns the result of serializing the <<scope-start>> of the rule
		(without the enclosing parentheses),
		or null if there is no <<scope-start>>.

		<dt><code>end</code> of type <code>CSSOMString</code>
		<dd>The <code>end</code> attribute
		returns the result of serializing the <<scope-end>> of the rule
		(without the enclosing parentheses),
		or null if there is no <<scope-end>>.
	</dl>

<!--
████████ ████████  ██████
██          ██    ██    ██
██          ██    ██
██████      ██    ██
██          ██    ██
██          ██    ██    ██
████████    ██     ██████
-->

<h2 id="changes">
Changes</h2>

This appendix is <em>informative</em>.

<h3 id="changes-since-2023-03">
Changes since the 21 March 2023 Working Draft</h3>

	Significant changes since the
	<a href="https://www.w3.org/TR/2023/WD-css-cascade-6-20230321/">21 March 2023 Working Draft</a> include:

	* Added the <code>@import scope()</code> syntax,
		and the ability to specificy ''layer()'', ''scope()'', and ''supports()''
		in any order.
		(<a href="https://github.com/w3c/csswg-drafts/issues/7348">Issue 7348</a>)

	* Defined ''&'' to behave like <code>:where(:scope)</code>.
		(<a href="https://github.com/w3c/csswg-drafts/issues/9740">Issue 9740</a>)

	* Allowed [=declarations=] directly within ''@scope''.
		(<a href="https://github.com/w3c/csswg-drafts/issues/10389">Issue 10389</a>)

	* The '':scope'' selector can match the [=featureless=] [=shadow host=] when
		that host is the [=scoping root=] element.
		(<a href="https://github.com/w3c/csswg-drafts/issues/9025">Issue 9025</a>)

	* ''<<scope-start>>'' and ''<<scope-end>>'' selectors are unforgiving.
		(<a href="https://github.com/w3c/csswg-drafts/issues/10042">Issue 10042</a>)

	* A ''@scope'' rule without ''<<scope-start>>'' scopes to the
		[=shadow host=] instead of the [=shadow root=].
		(<a href="https://github.com/w3c/csswg-drafts/issues/9178">Issue 9178</a>)

	* Clarified that [=scope proximity=] is a single measurement of the steps
		between a single [=scoping root=] and [=scoped style rule=] [=subject=]
		(<a href="https://github.com/w3c/csswg-drafts/issues/10795">Issue 10795</a>
		has been opened to discuss this futher).

	* Removed strong scope proximity.
		(<a href="https://github.com/w3c/csswg-drafts/issues/6790">Issue 6790</a>)

	* Removed the scoped descendant combinator (deferred).
		(<a href="https://github.com/w3c/csswg-drafts/issues/8628">Issue 8628</a>)

	* Added the {{CSSScopeRule}} interface.
		(<a href="https://github.com/w3c/csswg-drafts/issues/8626">Issue 8626</a>)

<h3 id="changes-2022-08">
Changes since the 21 December 2021 First Public Working Draft</h3>

	Significant changes since the
	<a href="https://www.w3.org/TR/2021/WD-css-cascade-6-20211221/">21 December 2021 First Public Working Draft</a> include:

	* Clarified ''@scope'' effects on nested '':scope'' and ''&'' selectors.
		(<a href="https://github.com/w3c/csswg-drafts/issues/8377">Issue 8377</a>)

	* Removed ''@scope'' prelude from specificity calculation.
		(<a href="https://github.com/w3c/csswg-drafts/issues/8500">Issue 8500</a>)

	* Specified how name-defining [=at-rules=] behave in ''@scope''.
		(<a href="https://github.com/w3c/csswg-drafts/issues/6895">Issue 6895</a>)

	* Added implicit scopes by making ''<<scope-start>>'' optional.
		(<a href="https://github.com/w3c/csswg-drafts/issues/6606">Issue 6606</a>)

	* Disallowed [=pseudo-elements=] in the ''@scope'' prelude.
		(<a href="https://github.com/w3c/csswg-drafts/issues/7382">Issue 7382</a>)

	* Removed selector scoping notation.
		(<a href="https://github.com/w3c/csswg-drafts/issues/7709">Issue 7709</a>)

	* [=Scoping limit=] elements are excluded from the resulting [=scope=].
		(<a href="https://github.com/w3c/csswg-drafts/issues/6577">Issue 6577</a>)

<h3 id="additions-l5">
Additions Since Level 5</h3>

	The following features have been added since
	<a href="https://www.w3.org/TR/css-cascade-5/">Level 5</a>:

	* 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


<h3 id="additions-l4">
Additions Since Level 4</h3>

	The following features have been added since
	<a href="https://www.w3.org/TR/css-cascade-4/">Level 4</a>:

	* 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.

<h3 id="additions-l3">
Additions Since Level 3</h3>

	The following features have been added since
	<a href="https://www.w3.org/TR/css-cascade-3/">Level 3</a>:

	* 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-cascade-4#aliasing]].
<!--
	* Added definition of how scoped styles would cascade
		(deferred from Level 3)
-->

<h3 id="changes-2">
Additions Since Level 2</h3>

	The following features have been added since
	<a href="http://www.w3.org/TR/CSS2/cascade.html">Level 2</a>:

	<ul>
		<li>The 'all' shorthand
		<li>The ''initial'' keyword
		<li>The ''unset'' keyword
		<li>Incorporation of animations and transitions into the <a>cascade</a>.
	</ul>

<h2 class="no-num" id="acknowledgments">Acknowledgments</h2>

	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.

<h2 id="privacy">
Privacy Considerations</h2>

	* 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.

<h2 id="security">
Security Considerations</h2>

	* 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 <a href="https://html.spec.whatwg.org/multipage/urls-and-fetching.html#content-type"><code>Content-Type</code> metadata</a>
		(or any same-origin file if the host document is in quirks mode)
		are <code>text/css</code>,
		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.
