If you’ve ever written CSS, you know the pain. You start styling a navigation menu, and suddenly you’re typing header nav ul li a for the tenth time, wondering if there’s a better way. Spoiler: there is, and it’s called CSS nesting.
What Actually Is CSS Nesting?
CSS nesting is exactly what it sounds like – you can nest CSS selectors inside other selectors, creating a hierarchical structure that mirrors your HTML. Instead of repeatedly writing out parent selectors, you group related styles together in one logical block.
Here’s the thing that surprised me: this isn’t a new concept at all. Developers have been using nesting since 2006 through preprocessors like Sass. What’s new is that it’s now native to CSS – your browser understands it directly, no build tools required.
A Quick History Lesson (I Promise It’s Relevant)
Back in 2006, a developer named Hampton Catlin created Sass (Syntactically Awesome Style Sheets). One of Sass’s killer features was nesting. Soon after, Less CSS came along with similar capabilities. For nearly 17 years, if you wanted to write nested CSS, you had to:
- Write your styles in Sass or Less
- Set up a build process
- Compile it back to traditional CSS
- Hope nothing broke in the process
Developers loved nesting so much they were willing to add entire build tools to their workflow just to use it. That tells you something about how useful it is.
Then, in 2023, CSS nesting finally became native. Chrome, Edge, Safari, and Firefox all added support. No more preprocessors needed (well, unless you’re using Sass for other features like mixins, which is fair).
The Problem CSS Nesting Solves
Let me show you with a real example. Here’s how you’d traditionally style a navigation header:
css
header {
background: #333;
padding: 1rem;
}
header nav {
display: flex;
gap: 2rem;
}
header nav ul {
list-style: none;
display: flex;
}
header nav a {
colour: white;
text-decoration: none;
}
header nav a:hover {
colour: #3498db;
}
Count how many times “header” appears. Five times! If you later decide to rename header to site-header, you need to find and replace it in five different places. Miss one, and your styles break.
Now here’s the same thing with CSS nesting:
css
header {
background: #333;
padding: 1rem;
nav {
display: flex;
gap: 2rem;
ul {
list-style: none;
display: flex;
}
a {
colour: white;
text-decoration: none;
&:hover {
colour: #3498db;
}
}
}
}
Look at that. You write “header” once, and everything inside is automatically scoped to it. All your header-related styles are in one logical block. If you need to rename it, you change it in one place. That’s it.
The Ampersand (&) Is Your New Best Friend
Notice that &:hover in the nested example? That ampersand is crucial to understanding CSS nesting.
The & symbol represents the parent selector. When the browser sees it, it replaces it with whatever the parent is. So:
&:hoverbecomesa:hover&:focusbecomesa:focus&::beforebecomesa::before
Here’s a more detailed example:
css
article {
padding: 2rem;
/* Creates: article h1 */
h1 {
font-size: 2rem;
}
/* Creates: article:hover */
&:hover {
box-shadow: 0 2px 8px rgba(0,0,0,0.1);
}
/* Creates: article::before */
&::before {
content: "📄";
}
}
Without the ampersand on h1, it creates a descendant selector (article h1). But with the ampersand, it applies the style to the article itself. This distinction is important – I got it wrong the first time I tried nesting and couldn’t work out why my hover states weren’t working!
Golden rule: Always use & before pseudo-classes (:hover, :focus, :active) and pseudo-elements (::before, ::after).
Real-World Use Case 1: Semantic HTML Structure
Let’s say you’re building a section with a header and some articles. Traditionally, your CSS would be scattered all over your stylesheet:
css
section { ... }
section header { ... }
section header h2 { ... }
section header p { ... }
section article { ... }
section article:last-child { ... }
That’s six separate selectors for one component. When you need to modify the section, you’re hunting through your entire CSS file.
With nesting, it’s all in one place:
css
section {
padding: 3rem 1rem;
header {
margin-bottom: 2rem;
h2 {
font-size: 2.5rem;
colour: #2c3e50;
}
p {
colour: #7f8c8d;
font-size: 1.1rem;
}
}
article {
margin-bottom: 1.5rem;
line-height: 1.6;
&:last-child {
margin-bottom: 0;
}
}
}
Everything section-related is together. The visual hierarchy in your CSS matches the HTML structure. When I need to change how sections work, I know exactly where to look.
Real-World Use Case 2: Responsive Media Queries
This one’s a game-changer. Traditionally, media queries are scattered throughout your CSS file. You have your base styles at the top, then scroll down to find @media (min-width: 768px) somewhere in the middle, then another media query at the bottom. It’s chaos.
With nesting, media queries live right next to the styles they modify:
css
article {
padding: 1rem;
h1 {
font-size: 1.5rem;
margin-bottom: 1rem;
}
p {
font-size: 1rem;
line-height: 1.5;
}
@media (min-width: 768px) {
padding: 2rem;
h1 {
font-size: 2.5rem;
}
p {
font-size: 1.125rem;
line-height: 1.7;
}
}
@media (min-width: 1024px) {
padding: 3rem;
max-width: 800px;
margin: 0 auto;
}
}
Now I can see at a glance: mobile padding is 1rem, tablet is 2rem, desktop is 3rem. The heading grows from 1.5rem to 2.5rem. Everything about this article’s responsive behaviour is in one place.
When I’m working on responsive design, this saves so much time. No more jumping between different parts of the file trying to remember what changes at which breakpoint.
Browser Support (It’s Actually Good!)
Here’s the exciting bit: CSS nesting has excellent browser support as of 2025.
- Chrome 112+ (April 2023)
- Edge 112+ (April 2023)
- Safari 16.5+ (May 2023)
- Firefox 117+ (August 2023)
According to Can I Use, we’re looking at over 90% global browser support. For most modern projects, that’s production-ready.
I checked the Can I Use data myself whilst preparing my presentation, and the support is genuinely impressive. All major browsers adopted it within a few months of each other in 2023.
When Should You Use CSS Nesting?
Green light scenarios:
- Modern web applications targeting 2023+ browsers
- Internal tools and dashboards where you control the browser environment
- Projects with defined browser requirements
- Component-based architectures (React, Vue, etc.)
Proceed with caution:
- Public-facing websites with diverse audiences
- Clients specifically requiring older browser support
- Projects where you don’t have analytics data on user browsers
Fallback option: If you need to support older browsers but still want to write nested CSS, use PostCSS with the postcss-nesting plugin. It’ll automatically transpile your nested CSS to traditional CSS during the build process. Best of both worlds.
Best Practices (Learn From My Mistakes)
1. Always Use the Ampersand for Pseudo-Classes
I learnt this the hard way. I forgot the & before :hover once and spent ages debugging why my hover states weren’t working. Don’t be like me.
css
/* ❌ Wrong - creates "article :hover" (note the space) */
article {
:hover {
background: red;
}
}
/* ✅ Correct - creates "article:hover" */
article {
&:hover {
background: red;
}
}
2. Don’t Nest Too Deeply
Maximum 3-4 levels. If you’re nesting more than that, your selectors become overly specific and hard to override.
css
/* ❌ Too deep - creates incredibly specific selectors */
main {
section {
article {
header {
h1 {
/* This creates: main section article header h1
That's a specificity nightmare! */
}
}
}
}
}
/* ✅ Better - flatter structure */
main {
section {
padding: 2rem;
}
article {
margin-bottom: 1rem;
}
h1 {
font-size: 2rem;
}
}
3. Use Nesting Where It Adds Value
Don’t nest just because you can. Only nest when it improves organisation and readability.
4. Keep an Eye on Specificity
Nesting increases specificity just like traditional nested selectors. main section h1 has the same specificity whether you write it traditionally or nested. Be mindful of this.
5. Test Across Target Browsers
Even though support is excellent, always test. I use BrowserStack for cross-browser testing in my projects.
Common Pitfalls to Avoid
Pitfall 1: Nesting Too Deeply
I already mentioned this in best practices, but it’s worth repeating because it’s the most common mistake. Five levels of nesting creates selectors like main section article header h1. That’s absurdly specific and nearly impossible to override without using !important (which you should avoid).
Pitfall 2: Forgetting the Ampersand
Without & before pseudo-classes, your styles won’t work as expected. The browser will look for a descendant element called :hover instead of applying the hover state to the parent.
Pitfall 3: Overusing Nesting
Just because you can nest doesn’t mean you should nest everything. If nesting doesn’t improve organisation, stick with traditional CSS.
Resources and Further Reading
If you want to dive deeper into CSS nesting, here are the resources I found most helpful:
- MDN Web Docs: CSS Nesting – Comprehensive documentation with examples
- Can I Use: CSS Nesting – Up-to-date browser support data
- W3C CSS Nesting Specification – The official spec (quite technical, but good for understanding edge cases)
- Sass Documentation – Understanding where nesting came from
- PostCSS Nesting Plugin – For backward compatibility
My Personal Take
After using CSS nesting in a few recent projects, I genuinely can’t imagine going back to traditional CSS for component-heavy work. The organisation benefits alone are worth it.
That said, I wouldn’t use it absolutely everywhere. For simple, one-off styles, traditional CSS is perfectly fine. But for anything component-based – navigation menus, cards, forms, footers – nesting makes the code so much more maintainable.
The fact that it’s now native means there’s no excuse not to try it. You don’t need to set up Sass or any build tools. Just write nested CSS and it works.
Leave a Reply