Title: CSS Cascading and Inheritance Level 6 Shortname: css-cascade Level: 6 Status: ED Prepare for TR: no Work Status: Exploring Group: csswg ED: https://drafts.csswg.org/css-cascade-6/ TR: https://www.w3.org/TR/css-cascade-6/ Editor: Elika J. Etemad / fantasai, Invited Expert, 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 spec:dom; type:dfn; for:tree; text:root 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: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 [=weak scoping 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;
}
}
B that is an arbitrary descendant
of some ancestor element A.
This combinator differs from the [=descendant combinator=]
in that it applies [=weak scoping proximity=]
to the relationship between <a> element's color will be determined
by the nearest ancestor with either
a ''light-scheme'' or ''dark-scheme'' class.
(If the descendant selector had been used,
its color would always be ''plum'',
because it is later in the source order.)
.light-scheme >> a { color: darkmagenta; }
.dark-scheme >> a { color: plum; }
However if the <a> element has a ''light-scheme''
ancestor and is focused,
its color will be ''teal''
even if it has a nearer ''dark-scheme'' ancestor,
because there is no equivalent ''dark-scheme'' rule.
.light-scheme >> a:focus { color: teal; }
CSSScopeRule interface
[Exposed=Window]
interface CSSScopeRule : CSSGroupingRule {
readonly attribute CSSOMString start;
readonly attribute CSSOMString end;
};
start of type CSSOMString
start attribute must return a value as follows:
end of type CSSOMString
end attribute must return a value as follows:
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.