Title: CSS Cascading and Inheritance 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,Informative Classes: ex
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: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:mediaqueries-5 spec:css-values-4 spec:css-fonts-4
@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%; } }
@scope (.media-object) to (.content > *) { img { border-radius: 50%; } .content { padding: 1em; } }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.
@scope (#hero) { img { border-radius: 50%; } } :where(#hero) img { border-radius: 50%; }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=].
main-component
and sub-component
)
and every element is marked as part of one or both scopes
using the data-scope
attribute:
<section data-scope="main-component"> <p data-scope="main-component">...<p> <!-- sub-component root is in both scopes --> <section data-scope="main-component sub-component"> <!-- children are only in the inner scope --> <p data-scope="sub-component">...<p> </section> </section>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; } }
@scope [(<where: * <>)]? [to (< >)]? { < > }
@scope (#my-component) { p { color: green; } :scope p { color: green; } }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; } }While the '':scope'' or ''&'' selectors can both refer to the [=scoping root=], they have otherwise different meanings in this context: : Differences in selector matching :: The '':scope'' selector will only match the [=scoping root=] itself, while the ''&'' selector is able to match any element that is matched by the <
<div> <style> @scope { p { color: red; } } </style> <p>this is red</p> </div> <p>not red</p>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>
/* .content is only a limit when it is a direct child of the :scope */ @scope (.media-object) to (:scope > .content) { ... }[=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 (.parent-scope) { @scope (:scope > .child-scope) to (:scope .limit) { :scope .content { color: red; } } }is equivalent to:
@scope (.parent-scope > .child-scope) to (.parent-scope > .child-scope .limit) { .parent-scope > .child-scope .content { color: red; } }
@scope (.foo) { border: 1px solid black; }is equivalent to:
@scope (.foo) { :where(:scope) { border: 1px solid black; } }
CSSScopeRule
interface[Exposed=Window] interface CSSScopeRule : CSSGroupingRule { readonly attribute CSSOMString? start; readonly attribute CSSOMString? end; };
start
of type CSSOMString
start
attribute
returns the result of serializing the <end
of type CSSOMString
end
attribute
returns the result of serializing the <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.