Help choose the syntax for CSS Nesting
The CSS Working Group is continuing a debate over the best way to define nesting in CSS. And if you are someone who writes CSS, we’d like your help.
Nesting is a super-popular feature of tools like Sass. It can save web developers time otherwise spent writing the same selectors over and over. And it can make code cleaner and easier to understand.
Everyone wishes CSS nesting could use the same kind of simple syntax that Sass does. That’s impossible, however, because of the way browser parsing engines work. If they see a sequence like element:pseudo
, they’ll parse the entire style rule as if it were a property: value
declaration.
So, a lengthy discussion began about what to do instead. Earlier this summer, the CSSWG debated between Option 1, Option 2 and Option 3. Of those, Option 3 won. Since then, two more options have been proposed, Option 4 and Option 5. If you remember various details discussed across 53+ issues, put all of those older ideas aside. At this point, we are only debating between Option 3, 4 and 5, as described in this article through the set of examples below.
To help us decide which option to choose, we’d like you to read these examples and answer a one-question survey.
Please look at these examples, consider how you write and maintain style sheets, and think deeply about which syntax you prefer. Then vote for the one you think is best.
In all three options, the &
symbol is a marker that means “put the selector that’s outside of the nest [here]”. For example…
Got it?
In many of the following examples, the &
is optional. Some developers will use it because it helps make their code more readable. Other developers will opt to leave it out, especially when copying & pasting code from unnested contexts. When the &
is left out, the outside selector is added at the beginning, as an ancestor. (When we surveyed authors, their opinions on use of optional &
were split 50/50.)
But here’s the key trick to Option 3 (and only Option 3) — if you are using an element selector (like p
, article
, or div
), the &
is required. If you are using any other selector, like a class or ID, you can choose to leave the &
out. The easiest way to remember this: the selector can never begin with a letter. It must begin with a symbol. Some people in the CSSWG believe this will be easy to remember and do. Others wonder, given that style rules placed anywhere else in CSS don’t have such a syntactic restriction, if it will create confusion, tripping up developers in a way that is hard to debug.
As you compare the options, think about how your whole team will handle nested code. Think about what it might be like to copy & paste code from one project to another. Which option will make it easy to code inside and outside a nested context? Which will make it easiest to read, write, and edit large quantities of CSS?
Which is best for the future of CSS? When people write CSS thirty years from now — long after today’s habits and expectations are completely forgotten, when future generations have never heard of Sass — which option will make writing this language easy and elegant?
Do be sure to read through all the examples. One option might stand out as your favorite in one example, and yet, have problems that you don’t like in another example.
Comparing the Options
- Option 5: Top-level @nest: Nested style rules are declared in a dedicated, independent at-rule that accepts only style rules. Declarations can be nested using & { .. }.
- Option 4: Postfix block: Style rules allow for an optional, second block after the declaration block that contains only style rules.
- Option 3: Non-letter start: Nested style rules can be added directly into a declaration block, but cannot start with a letter.
Example A: The Basics
Example B: With syntax variations
There are a lot of different ways developers like to structure their CSS — using tabs vs spaces, putting the {
}
braces on the same line as a rule or on separate lines, ordering rules in a certain order. This will also be true when writing nested CSS. Example B articulates a few of the possible variations of how you might format nested code for each option. It’s totally up to your personal preference.
Example C: Re-nesting inside an element selector
There is a situation for Option 3 where just using an &
is not enough — when we want the parent selectors referenced by &
to come after the nested selector. Since we can’t start with &
, we need to use something like :is()
or :where()
in order to start with a symbol instead of a letter.
Example D: Zero unnested declarations + various selectors
Example E: Nesting inside of nesting
Example F: Integration with Media Queries
Example G: Integration with Cascade Layers
Now that you’ve had a chance to absorb examples of the three options, and maybe play around with a few of your own, which do you believe should become the way CSS is written in the future?
Which option is best for the future of CSS?
-
Option 59%
-
Option 45%
-
Option 386%
If you’d like to describe more about your thoughts, reply to @webkit on Twitter, or @jensimmons@front-end.social on Mastodon.
Thank you for your feedback. There’s a lot that goes into designing a programming language, not just the results of a survey like this. But knowing what web developers think after reading examples will help us with our ongoing discussions.
Please pass along this survey to other people you know who also write CSS, post it to social media, and help us get the word out. The more people who voice their opinion, the better.
We especially want to hear from developers working on a wide variety of projects — from websites to web apps, native apps to digital signage to printed books. Whether large and small projects, huge or tiny teams, brand-new or decades-old codebases. Built on any variety of frameworks, CMSes, build systems… dynamic or static, rendered server-side or client-side… there are a lot of ways people use CSS, all around the globe. We need to consider them all.