This content originally appeared on Manuel Matuzović - Blog and was authored by Manuel Matuzović
There are different ways of selecting the scoping root inside a @scope
rule.
When you use the :scope
pseudo-class in a stylesheet, it matches the :root
element.
:root {
border: 10px solid red;
}
:scope {
border-color: blue;
}
/* -> 10px blue border on the <html> element */
When you use it inside a scope rule, it matches the rule's scoping root.
<div class="wrapper">
<div class="content">
the cascade is unavoidable
</div>
</div>
@scope (.wrapper) {
:scope {
border: 5px solid red;
}
}
/* -> 5px red border on the .wrapper element */
Selectors inside a scope rule can only match elements that are in scope. Selecting .content
within the .wrapper
scope works:
@scope (.wrapper) {
.content {
background: aqua;
}
}
/* That's like writing .wrapper .content {} */
Selecting .wrapper .content
within the .wrapper
scope doesn't work:
@scope (.wrapper) {
.wrapper .content {
background: aqua;
}
}
/* That's like writing .wrapper .wrapper .content {} */
You can use :scope
instead of .wrapper
. That works because it doesn't match an element with the class .wrapper
inside of .wrapper
, but the scoping root itself.
@scope (.wrapper) {
:scope .content {
background: aqua;
}
}
/* That's like writing .wrapper .content {} */
Instead of :scope
, you can also use &
.
@scope (.wrapper) {
& {
border: 5px solid orange;
}
& .content {
background: aqua;
}
}
/*
-> 5px orange border on the .wrapper element
and aqua background on .content.
*/
There are two differences between :scope
and &
in this context. They're only evident if you have a list of scoping roots.
The first difference in specificity. :scope
has the specificity of a pseudo-class. &
takes on the specificity of the most specific selector in the selector list of scoping roots. In the following example :scope
overrules &
because &
has the specificity of a tag selector.
<section id="section">
<h2>
<span>yo!</span>
</h2>
<p>
<span>yo!</span>
</p>
</section>
@scope (section, p) {
:scope {
border: 10px solid green;
}
& {
border: 10px solid red;
}
}
/* -> 10px green border on section and p */
If you scope the section via its id instead of the tag, &
takes on the specificity of an id selector and thus overrules :scope
.
@scope (#section, p) {
& {
border: 10px solid red;
}
:scope {
border: 10px solid green;
}
}
/* -> 10px red border on the section and p */
The second difference is that :scope
only matches the scoping root itself. &
can match any element that is matched by the selector list.
<section>
<h2>
<span>yo!</span>
</h2>
<p>
<span>yo!</span>
</p>
</section>
@scope (section, p) {
:scope span { background: fuchsia; }
/*
section span { }
p span { }
-> fuchsia background on span within h2 and p
*/
:scope & span { background: aqua; }
/*
section p span { }
-> aqua background only on span within p
*/
:scope :scope span { background: red }
/*
Doesn't match any element because `@scope (section, p)` only
defines multiple scopes, it doesn't nest them.
*/
}
Essentially, that means that :scope
can only match a scoping root and &
can match an element in the selector list, regardless of whether it's considered a scoping root in that context. At least, that's how I interpret it. The spec is still pretty fucking hard to read.
To try out @scope
you have to download Chrome Canary and enable the Experimental Web Platform features
flag in chrome://flags/.
My blog doesn't support comments yet, but you can reply via blog@matuzo.at.
This content originally appeared on Manuel Matuzović - Blog and was authored by Manuel Matuzović
Manuel Matuzović | Sciencx (2023-09-01T00:00:00+00:00) Day 102: selecting the scoping root. Retrieved from https://www.scien.cx/2023/09/01/day-102-selecting-the-scoping-root/
Please log in to upload a file.
There are no updates yet.
Click the Upload button above to add an update.