In short
Native CSS nesting lets you write child rules inside parent rules, and cascade layers (@layer) let you control which group of styles wins in big projects. What is native CSS nesting? In the past, you needed a tool like Sass to nest CSS rules. Now browsers support nesting directly.
Native CSS nesting lets you write child rules inside parent rules, and cascade layers (@layer) let you control which group of styles wins in big projects.
What is native CSS nesting?
In the past, you needed a tool like Sass to nest CSS rules. Now browsers support nesting directly. You can write a rule inside another rule, and the inner selector is joined to the outer one.
This keeps related styles together, like keeping all the parts of a recipe on one card.
<nav class="main-nav">
<a href="/">Home</a>
<a href="/courses" class="active">Courses</a>
<a href="/about">About</a>
</nav>
.main-nav {
display: flex;
gap: 1rem;
padding: 1rem;
background: #1f2937;
a {
color: #e5e7eb;
text-decoration: none;
padding: 0.4rem 0.8rem;
border-radius: 6px;
&:hover {
background: #374151;
}
&.active {
background: #4f46e5;
color: white;
}
}
@media (max-width: 500px) {
flex-direction: column;
}
}
The browser reads this as .main-nav a, .main-nav a:hover and .main-nav a.active. You even nested a media query, which applies to .main-nav only on small screens.
How does the & symbol work in CSS nesting?
The & stands for "the parent selector". You need it when there should be no space between the parent and the nested part:
&:hoverbecomesa:hover(the link when hovered).&.activebecomesa.active(a link that also has the class)..dark-theme &becomes.dark-theme a(puts the parent at the end).
Without &, a nested selector always means "a descendant". So writing :hover alone inside a would mean "any hovered element inside the link", which is not what you want.
Common mistake: Nesting too deeply. Four or five levels of nesting create long, very specific selectors that are hard to override. Try to stay at two or three levels.
Note: Unlike Sass, native nesting cannot join text to build class names.
&__titledoes not create.card__title. Write the full class name instead.
What are cascade layers (@layer)?
In a big project, styles come from many places: a reset, base styles, components, utility classes, maybe a library. Normally the winner depends on specificity and source order, which can turn into a fight of longer and longer selectors.
Cascade layers let you put styles into named groups and decide the order of those groups yourself. A later layer always beats an earlier layer, no matter how specific the selectors are inside them.
Think of layers like sheets of transparent paper stacked on top of each other. Whatever is on the top sheet is what you see, even if the drawing underneath is more detailed.
Setting up reset, base, components and utilities layers
First, declare the order in one line at the very top of your CSS. Then put rules into each layer:
@layer reset, base, components, utilities;
@layer reset {
*, *::before, *::after {
box-sizing: border-box;
}
body {
margin: 0;
}
}
@layer base {
body {
font-family: system-ui, sans-serif;
line-height: 1.6;
}
a {
color: #4f46e5;
}
}
@layer components {
.btn {
display: inline-block;
padding: 0.6rem 1.2rem;
background: #4f46e5;
color: white;
border-radius: 6px;
}
#signup .btn {
background: #16a34a;
}
}
@layer utilities {
.bg-red {
background: #dc2626;
}
}
Now <a class="btn bg-red"> inside #signup gets a red background. The selector #signup .btn has an ID and is much more specific than .bg-red. But utilities is a later layer, so it wins. Utility classes now always work, as they should.
Some important rules about layers:
- The order in the first
@layerline is the order that counts, even if you write the layers in a different order in the file. - Styles that are not in any layer beat all layered styles.
- With
!important, the order flips: an important rule in an early layer beats an important rule in a later layer.
You can also put a whole library file into a low layer: @import url("library.css") layer(library);. Then your own styles easily override it.
Tip: Cascade layers do not replace specificity. Inside one layer, specificity and source order work exactly as before. Layers only decide which group wins first.
Why nesting and layers help big projects
- Nesting keeps everything about one component in one block, so it is easier to find, move or delete.
- Layers stop "specificity wars". You do not need
!importantor long selectors just to beat a reset or a library. - Together they make the CSS easier for a team to read, because the structure of the file shows how the styles relate.
Practice exercise
Write a small stylesheet with three layers: reset, components and utilities. In components, create a nested .card rule with a nested h3, a &:hover state and a nested media query. In utilities, add a .text-center class and check that it beats any text-align you set in the card.
Hint: Declare @layer reset, components, utilities; first, and test by adding class="card text-center" to an element.
Key takeaways
- Native CSS nesting lets you write rules inside other rules, no Sass needed.
- Use
&when the nested part attaches directly, like&:hoveror&.active. - Keep nesting shallow to avoid very specific selectors.
@layersets the order of style groups; later layers win over earlier ones.- Unlayered styles beat layered ones, and
!importantreverses the layer order.