CSS continues to offer new ways to select things in ways we never could’ve imagined in the past (especially for an old timer like me). Today I want to focus on a possible (but not always probable) use-case:
I have exactly n elements in a container. How can I do something only when all elements have <class>?
Let’s talk about two CSS pseudo selectors that can make that possible

First let’s assume some markup
Let’s start with a table containing exactly 7 columns across two rows. One row has someClass applied to some of the cells. Another row has it applied to all of the cells.
Our goal is to hide the row containing someClass on all seven cells.
<table>
<tbody>
<tr>
<td>
0
</td>
<td class=someClass>
zero
</td>
<td class=someClass>
ain
</td>
<td class=someClass>
nul
</td>
<td>
zero
</td>
<td>
zero
</td>
<td class=someClass>
nula
</td>
</tr>
<tr>
<td class=someClass>
1
</td>
<td class=someClass>
uno
</td>
<td class=someClass>
echad
</td>
<td class=someClass>
un
</td>
<td class=someClass>
uno
</td>
<td class=someClass>
one
</td>
<td class=someClass>
adin
</td>
</tr>
</tbody>
</table>
Use :has() and profit
The first approach only works in Safari right now, but it will eventually be available in all browsers
tr:has(.someClass:first-child:nth-last-child(7)) {
display: none;
}
What does it target?
Remember that CSS selectors are read from right to left, so let’s do exactly that:
- An element that is a
trhas…- an element that is the seventh-from-last,
- that is also the first-child,
- that has the class someClass
:has() is a “parent selector”. We’ve used it to tell the browser, “if a parent has a first-child of a set of exactly seven, set the parent to not display”.
Use :is() , some pseudo-selector shenanigans, and a beer
Ten years ago I wrote a blog post on pseudo-selector patterns that were pretty stonking powerful for the time. But there was a small limitation in that the structural pseudo-selectors work by the element’s order in the DOM, not by how many classes (or any thing else) were present.
In other words, .someClass:nth-child(7) isn’t targeting the seventh someClass — but the seventh element that is someClass. That’s a subtle difference that’s really annoying.
But we can circumvent it now!
.someClass:first-child:nth-last-child(7),
.someClass:first-child:nth-last-child(7) ~ .someClass:is(.someClass + .someClass){
display: none
}
What does it target?
- An element that is the seventh-from-last,
- that is also the first in the set
- that is also someClass
- An element that is someClass coming right after someClass
- that is also someClass
- that comes anywhere after an element that is the seventh-from-last
- that is also the first in the set
- that is also someClass
In other words, we’re telling the browser “get the first of a set of exactly seven. Now get the first of exactly seven and any someClass that are after it — but only if any of those that come after are right after each other.”
It’s a bit of a mind bend, but it works on the principle of, “if the first one in this set of seven doesn’t have this class, don’t bother. But if it does, then any of them after should have the class but with a catch, in any of that set, the one to precede it must have the class.”
Effectively, the adjacent sibling selector ( + ) nested inside of :is() became a positive lookbehind for us.
Pretty wild, huh?
Check out the CodePen if you don’t believe me
See the Pen Targeting exactly N classes in CSS by Paceaux (@paceaux) on CodePen.
Footnotes, Sources, and Whatnots
Credit to Michael Callaghan for presenting this challenge on Twitter. You should buy one of his books.