How to use native Nesting syntax in CSS (updated)
A year has passed since this article was written. Since then, the CSS Nesting specification has changed. There have been significant changes to it, so I'm posting an updated article.
The CSS Nesting
syntax was significantly impacted by the nested selectors syntax of the Sass
preprocessor. Many frontenders find it difficult to drop preprocessors in favor of native CSS, precisely because of the lack of nesting. In order to improve DX (developer experience) the CSS working group decided to introduce nested selectors.
Although the syntax is very similar, there are still some minor differences.
CSS syntax
Media queries inside nested selectors
For me, the most desired change was the ability to write media expressions inside nested selectors. For example, let's go back to the code described in the article about the new media expression syntax.
Classic variant:
.teaser__image {
width: 100%;
}
@media (width < 620px) {
.teaser__image {
width: 100px;
}
}
@media (620px <= width <= 768px) {
.teaser__image {
width: 180px;
}
}
Using CSS nesting:
.teaser__image {
width: 100%;
@media (width < 620px) {
width: 100px;
}
@media (620px <= width <= 768px) {
width: 180px;
}
}
Note that I am using the new media expression syntax. You can use the old syntax if you like.
The nested syntax makes the code much easier to read and more intuitive. Plus, it's a native browser behavior, and we won't need to install additional preprocessors like Sass
, Less
to achieve that behavior.
Nesting of selectors
This behavior is familiar from the preprocessors. A recent version of the specification introduced a change that removes the mandatory writing of the &
ampersand.
.teaser__image {
background: lightgray;
img {
display: block;
}
}
figure {
margin: 0;
> figcaption {
background: lightgray;
> p {
font-size: 0.9rem;
}
}
}
Although in some cases, the ampersand is mandatory.
button {
&:hover {
background-color: red;
}
&:focus {
background-color: blue;
}
}
More details on the syntax can be found in the specification.
Concatenation of strings
.block {
color: blue;
&__element {
color: red;
}
}
This behavior in CSS Nesting
, as specified in the spec, will not work. Too many heuristics for browsers.
@nest rule is gone!
The @nest
rule existed in early drafts of the specification, then after a user poll, it was removed.
More details about the syntax can be found in the specification.
Although the new syntax has already been approved, there is an online poll by the spec developers started recently, asking us to choose syntax options.
Enable the new syntax right now
Until the new syntax has reached full support for all browsers, we will enable the new features of the CSS Nesting
specification using PostCSS
.
Install the PostCSS
plugin:
npm i -D postcss postcss-nesting
Create a file postcss.config.js
to configure PostCSS
.
const postcssNesting = require('postcss-nesting');
module.exports = {
plugins: [postcssNesting],
};
As a result, the output of PostCSS
code will be compiled into native CSS
, understandable by all browsers.
I described more about how to connect PostCSS
to Gulp
, Eleventy
, Nuxt
in this article.
Note also that there is a postcss-nested
plugin, but at the moment I prefer to use the postcss-nesting
plugin, which correctly implements the latest version of the CSSWG specification.
References: