Browsing caniuse.com the other day, I found a pleasant surprise: a little green flag in a red box for a feature I'd been waiting for a long time.
CSS nesting will soon be supported on Chrome:
Yes, it's behind a flag and only in future versions, but it is a huge step forward. Those versions will soon be available, and we can try it locally (unfortunately, not on production without a polyfill or a plugin).
I can't wait for the table above to slowly start turning green. It will be big and could, little by little, reduce the dependency on libraries like Sass or Less. (Nothing against them, but it would be nice to have some of that behavior natively... I can only dream of having loops and functions one day.)
Not everyone shares my excitement. After sharing a post about this on social media, I quickly got some replies indicating that the nesting is no more than some syntactic sugar or not a significant improvement.
While it is true that it can be seen as syntactic sugar –some of the things we can achieve with CSS nesting can be achieved with combinators, too–; the critical part here is the "some" part. We can do some things with CSS nesting that cannot be done with combinators (e.g., styling pseudo-elements).
And even if we consider CSS Nesting syntactic sugar, where is the problem? Anything that helps organize the code, making it more robust, portable, and maintainable, should be welcomed. And that's what CSS nesting does: it allows grouping and encapsulating styles (in a similar way to how Sass or Less do it), and that will reduce common errors caused by poor code architecture/organization (like when people complain that changing a style in one page affects the styles on a different page.)
What is CSS Nesting?
This article was not intended to be a deep dive into CSS Nesting, more of an informational thing. The module is going through major updates and the notation displayed below may not match the final notation. If you want to learn more about CSS Nesting, check the W3C Editor's Draft, or Kilian Valkhof's article on CSS Nesting and Specificity.
With CSS Nesting, we can place one CSS rule inside of another (nest rules), and the selector of the child rule will be relative to the selector of the parent rule.
This is helpful for the modularization and maintainability of the code. Things that were exclusive to CSS preprocessors are possible in a native way.
Let's imagine that we have this code in CSS:
.blog-post {
margin-bottom: 3rem;
}
.blog-post .large-paragraph {
font-size: 1.5rem;
}
.blog-post .large-paragraph a {
text-decoration: underline;
}
.blog-post .large-paragraph a:hover {
text-decoration: wavy underline;
}
@media (min-width > 1024px) {
.blog-post .large-paragraph {
font-size: 2rem;
}
}
With CSS Nesting, we can nest the children making the code more organized. In a similar fashion to what CSS preprocessors like Sass or Less do:
.blog-post {
margin-bottom: 3rem;
.large-paragraph {
font-size: 1.5rem;
@media (min-width > 1024px) {
font-size: 2rem;
}
a {
text-decoration: underline;
&:hover {
text-decoration: wavy underline;
}
}
}
}
Both ways will translate into the same CSS code for the browser. So there won't be any difference between the two.
Specificity
There will be some differences when calculating the specificity, especially when there is more than one selector in a rule:
article, .blog-post {
& .large-paragraph {
font-size: 1.5rem;
}
}
That code above will be equivalent to the following:
:is(article, .blog-post) .large-paragraph {
font-size: 1.5rem;
}
Because it is equivalent to an :is()
, the larger of the specificities will be used in the &
. This may lead to confusion. For example, in the code above, an article
with a .large-paragraph
will have the same specificity as two classes instead of one class and one element.
Ideally, that won't be a big problem because our CSS will be more modular, and we won't find unpleasant surprises.
As mentioned above, this module is hot, and the specification is constantly updated. When writing this article, the latest draft is less than a month old, and many changes are still coming. So the notation displayed in this article may change. For example, just a few weeks ago, there was a big poll to gather information from developers and decide on the best syntax to move forward (spoiler alert: option 3 won). Also, the @nest
at-rule has been dropped in the latest versions of the draft, one reason why it was not mentioned.
I believe this technique will be beneficial for organizing code and avoiding human errors, and I can't wait until it is available in all browsers.
Top comments (21)
Would it be too pessimistic to say "Meh, firefox will probably just kill it like every other good thing in the web"?
I'm probably being a bit hard on firefox here, but JFC every single feature I want seems to be waiting for them to finally implement it.
You mean Safari
I ha(v/t)e to admit that Safari has been doing a good job lately. While it is way behind in features and options, some of the latest CSS things pop up on Safari first... which doesn't make much sense, but oh well...
Doesn't safari actually still have TCO in its javascript engine, even though firefox unilaterally decided to kill that feature for no reason whatsoever?
Automatically x3 times better if you ask me
The main reasons I use SCSS/SASS is because of nesting and variables. If they fix those two we are getting closer to not needing to compile everything, that would be huge.
But I have some other things, like functions or using a variable in a function call that I really like to see as well.
What do you need variables for that you cannot do with custom properties already?
I had some issues with trying to make the border of div transparent but not the element itself (else a opacity filter would have worked).
So instead I wanted to do:
But then with a variable instead as I wanted to make a light and dark togglable theme. But I found out that using css variables in this context doesn't work.
Maybe I am doing something wrong (or Firefox doesn't allow this?).
Well, no, that doesn't work, because
argb
isn't a thing, and if you want to usergb
you'll have to provide R, G and B separately.What you can do, for example:
and I'm 90% sure you can combine those three variables into a
--theme-hsl
variable somehow but cba to test it right now so won't include it in the code.EDIT: And of course, once CSS Color Module Level 5 becomes a thing, you can just do
Thanks for your explanation, I don't really do front-end that much (I do Java backend at work) but I never knew you could to things like this. Thanks!
argb isn’t a thing as mentioned, but rgba is, which is what you’re writing in the sample code anyways. R G and B go from 0 to 255, and A goes from 0.0 to 1.0
Сongratulations 🥳! Your article hit the top posts for the week - dev.to/fruntend/top-10-posts-for-f...
Keep it up 👍
Cool makes work much easier 👍🏽!
Css is going to get much easier now, thank you for sharing, can't wait for this feature :)
I was using sass/scss just because it is so much better to have nested css instructions. Love to see this feature becoming a standard...
This is a nightmare. Css should only define styles, not handle logic. Javascript is enough logic to handle already
How is this logic?
If (thing a is nested in thing b)
Apply style to thing a
Now what if I don't want to use thing b anymore but thing a? Then I have to change the css file, even though that makes no sense at all
That is how it happens right now in CSS when you put two selectors together (even without the nesting):
Those styles apply to the
.door
in a.car
, but not to a.door
inside a.house
.With CSS nesting this will be more evident for the developer:
It's just syntactic sugar that helps keep the code more organized and clean. The main danger is getting into the curly braces hell.
Fair enough. Still I would rather move in a direction where logic is handled in Javascript and css is styling and only styling. Just today I had to debug some complex sass function. That's hell. But of course this is subjective
Nesting is not logic in any way that makes the code more difficult to read when used properly and doesn't muddy seperation of concerns in any meaningful way. Once you get really adept at SCSS/Sass you start to be able to nest in ways that are intuitive, elegent and make the code a joy to read and reason about.
If you're having to debug a complex Sass function that's not intuitive, it is 100% not an issue with nesting, and everything to do with the developer not doing stuff properly. If you're struggling here then SonarCloud has some really neat features for helping to organise such code. If it's really bad it'll throw a proper riot-tantrum initially, but if you can find anyone good enough to actually fix issues it flags then you'll see what good nesting does for you.
@alvaromontoro by the way, thoughts on
@scope
?