Is CSS Nesting a good thing?
CSS Nesting is coming to the CSS specification and will soon land in all browsers. As I have never been a fan of SASS and particularly nesting, I’m not excited by this addition.
What is about, and how does it work?
Instead of writing the following:
.fridge .fruit.apple {
color: red;
}
You can nest selectors like this:
.fridge {
.fruit {
&.apple {
color: red;
}
}
}
Why would we add something that lets you do the same job differently? Is the latter code better than the former ? Maybe and maybe not. It depends on taste and other things you might take into consideration. Note that this is a trivial example, and nesting will reduce lines of code in some situations.
Notice the ampersand.
&
is called the nesting selector.
It lets you reference the parent or outer selector in a nesting context.
The position of the &
matters.
In effect, you can do the following.
.fruits {
/* equivalent to .fruits.apple */
&.apple {
color: red;
}
/* equivalent to .fruits .apple */
& .apple {
color: red;
}
/* equivalent to .fruits .apple .fruits */
.apple & {
color: red;
}
}
I recommend reading these articles to learn more12.
Adding Suffixes
Nesting in SASS makes searching a pain.
If you encounter class="btn__icon"
in your HTML and want to find where it is defined, you can’t just search for btn__icon
.
This may no longer be a strong argument in the era of scoping and CSS-in-JS because it can help you narrow down where to search.
Fortunately, the current implementation of nesting doesn’t support concatenating suffixes like in SASS .
.button {
&--icon {
/* is not equal to ".button--icon" */
}
& .button--icon {
/* is equal to ".button--icon" */
}
}
However, concatenating suffixes is one of the selling points of SASS, particularly for BEM fans. This makes nesting in vanilla CSS less powerful than nesting in SASS. Why bother adding something subpar ? Won’t it make adoption less successful ?
Legibility & Cognitive Overload
Nesting let you create a mini-cascade inside the cascade. In a way, it is not dissimilar to nested if statements. Similarly, too deeply nested selectors become a pain to understand and a code smell.
When coding, my goal is to write code that is easy to read and comprehend in the future. Often, repeating yourself is better than making a mess for the future by using shortcuts. Let me take a silly example that exaggerates what we can write for the sake of the argument.
You could write this :
main .birds .are .nesting {
color: red;
}
main.spring .birds .are .nesting {
color: green;
}
But also this:
main {
.birds {
.are {
.nesting {
color: red;
}
}
}
&.spring {
.birds {
.are {
.nesting {
color: green;
}
}
}
}
}
The most highly cited paper in psychology argues that the number of objects an average human can hold in short-term memory is 7±23. Cognitive overload happens when your working memory receives more information than it can handle comfortably, leading to poor performance.
From the above example, you can see how nesting can make it harder to understand what is going on because one needs to remember all the parent selectors that led to the statement you are focusing on. I personally struggle reading nested CSS because of that. Well, you could say that this is not the CSS Nesting specification problem; it is a people problem. As you can’t force people to write elegant code without too many nested if statements, you cannot stop people from misusing nesting.
On the other side, nesting works well for things like media queries. The grouping makes sense.
.foo {
display: grid;
&.highlight {
color: green;
}
@media (orientation: landscape) {
grid-auto-flow: column;
&.highlight {
color : red;
}
}
}
End note
I would rather not have CSS nesting for all the reasons I explained before. I will use it here and there, with precaution, where it makes sense and increases readability. Also, setting up and defining linter rules and conventions will help enforce good practices. Ultimately, I see CSS as a low-level language like C. And it’s great that people create higher-level tools like SASS that compile back to CSS. But CSS should stay small and nimble. Everything you can do with nesting can be done without. But now, we will have multiple ways of writing the same code. My question is, why would you open the door for that ?
Footnotes
-
Cognitive Load Theory, Learning Difficulty, and Instructional Design. John Sweller. ↩