There is a working draft spec for CSS scoping now. Other than a weird period where <style scoped>
shipped and then was subsequently removed from the spec (and browsers), this is the furthest a scoping proposal has gotten (the Level 1 spec never got anywhere).
This one comes from Miriam Suzanne.
The basics:
<div class="media">
<img alt="Proper alt." src="...">
<div class="content">
<p>...</p>
</div>
</div>
If I’m thinking of this bit of HTML as a “component,” it’s nice to be able to write styles for it that are very explicitly just for it. That’s what @scope
is for, so…
@scope (.media) {
:scope {
display: grid;
grid-template-columns: 50px 1fr;
}
img {
filter: grayscale(100%);
border-radius: 50%;
}
.content { ... }
}
What I like about that is:
- This bit of CSS is very explicitly for this media component. It reads like that and can be maintained like that.
- I didn’t have to come up with a name and class for the
<img>
. I’m applying styling there without it “leaking out” to other images.
But wait, isn’t this just like prepending selectors with the parent class?
It kind of is… like we could also write:
.media {
}
.media img {
}
.media .content {
}
And now we’ve scoped things internal to the media component. That’s rather repetitive, but with native CSS nesting on the way, it’s just this:
.media {
& img {
}
& .content {
}
}
So yes, I’d say nesting takes care of some basic types of scoping, but there are some things that are very unique to this new scope proposal.
One unique feature is “donut scope” meaning I stop the scoping where I want to. Maybe I want my scoping to stop at a particular class:
@scope (.media) to (.content) {
p { }
}
Now I can write styles that won’t mess with areas that I don’t want them to mess with. Perhaps:
<div class="media">
<img alt="Proper alt." src="...">
<p>This is stylable in scope.</p>
<div class="content">
<p>This is NOT styleable in scope.</p>
</div>
</div>
But that’s not the only unique problem this new spec solves. I think the “nearest ancestor” situation that Miriam lays out is perhaps the most interesting thing. I’ll send you over to the blog post to read about that — it’s pretty wild that we don’t have a good tool for that yet.
There is a lot to wrap your mind around here, especially as you think of more complex situations, like multiple overlapping scopes and how the nesting syntax might interplay with scoping. Fortunately, Miriam is blogging these things very clearly.
The 4th example is SCSS/Less, not valid native nested direct selectors. The latter (as proposed) must start with
&
:Aw shucks I thought it was gonna be like if you are just doing a simple nested selector you could omit the &. I’m probably wrong
Why a browser should be dump to not be able for handling it without necessary &-?!
I wish it was, but it won’t be to avoid infinite look-ahead to distinguish between a declaration and a nested selector.
Spec), see “Why can’t everything be directly nested?” just above.
To my great sadness this will make the refactoring step of wrapping (nesting) a group of rule-sets with an additional selector non-trivial and tedious, but the reasoning makes sense from the perspective of parser performance: every declaration would have to be processed twice, first to find the ending
;
or{
, then to parse as a declaration/selector (respectively).One approach was attempted to make the nest-prefix optional, but not investigated in great detail: #5746
There was a similar question for @nest (not direct nesting): #5738
Their proposed
to
clause, as seen in the example of@scope (.media) to (.content)
, can come in handy.If the word “to” can be changed to “until”, it would be less confusing.
Disagree, if I run from my .home to the .stopsign that is where I stop, I don’t go beyond it. Makes sense to me.
Wow. We’ve been waiting for this for years….
I keep returning to this hoping the proposed syntax seems less strange. I understand it fine but I can really see its use leading to complete carnage in large projects.
Mixing up the @ syntax, used mostly for environment checking (media query, supports etc) with the selector process reminds me of last-chance browser-targeting hacks. The whole thing just seems a bit yucky compared to the nested proposals which feel more true to CSS.