A few fun nesting tips & tricks
Published on
Native CSS nesting is starting to have pretty good support numbers, which means we’ll probably start seeing it used more and more in production, so I wanted to share a few fun nesting tips & tricks with you.
We’ll start with a simple one that I use the most often, and step things up from there.
Nesting media queries
I realize that not everyone is onboard with nesting, but I think the gateway into using it more for a lot of people is nested media queries.
.grid {
display: grid;
gap: 1rem;
@media (width > 720px) {
grid-template-columns: repeat(3, 1fr);
}
@media (width: 1200px) {
grid-template-columns: repeat(5, 1fr);
}
}
All we’re saving here is repeating the .grid
selector inside a couple of media queries, but that alone is so nice. On top of that, I like how it keeps all the styling for my grid in a single rule.
Easier centered text
Based on the conversations I have with people, I know I’m not the only one who likes to do something like this:
p {
max-inline-size: 65ch;
}
If you’ve ever done this, you may have also run into the problem where you have a section with center aligned text as well.
See the Pen max line-length centered is a problem by Kevin (@kevinpowell) on CodePen.
We could do something like this:
.text-center {
text-align: center;
}
.text-center > p {
margin-inline: auto;
}
And that works, but with nesting, we can do the same thing while keeping all the styles with our original paragraph selector.
p {
max-inline-size: 65ch;
.text-center > & {
margin-inline: auto;
}
}
This looks a little strange. Most use cases of nesting have the &
placeholder at the start of a selector, not the end of it, but this works and gives us the same result as that first code block.
Some people won’t like this because it looks unfamiliar, and it might not be for everyone, but I think it’s pretty handy that I can keep all my paragraph related styles in one rule.
Forcing a style on a parent element
This is where we get into the realm of use with caution, but it’s also what inspired me to write this post as I think it can be pretty handy.
Using a similar trick to what we did above, we can nest a :has()
selector, and use the &
inside of it to select the parent of a given element, like so:
.example {
:has(> &) {
/* style the parent here */
}
}
If you’re looking at this thinking “This is a bad idea”, you’re probably right, but I do think in certain spots, it can come in handy.
For example, if ever you have a decorative pseudo-element with a negative z-index, it has the potential to go too far back.
See the Pen negative z-index problem by Kevin (@kevinpowell) on CodePen.
To prevent this from happening, we need to create a new stacking context somewhere.
One option is to create that context on the parent element itself, but then the decorative element doesn’t go behind the background of the element…
See the Pen negative z-index problem by Kevin (@kevinpowell) on CodePen.
Usually, I’ll take that approach, but then add a second pseudo-element to replace the regular background of my element, stacking them in the right order so that it all looks fine.
And while we could do that, using :has()
, we can also do this instead:
.example {
/* some styles */
&::after {
position: absolute;
z-index: -1;
/* some more styles styles */
}
:has(> &) {
/* force the parent of .example
to create a new stacking context */
isolation: isolate;
}
}
And this works!
See the Pen negative z-index problem - oh no, that’s worse! by Kevin (@kevinpowell) on CodePen.
I don’t want to be responsible for people causing all sorts of problems using this, so again, file this one under use with caution… but in the right situation, this feels like it could come in handy.