This content originally appeared on Bram.us and was authored by Bramus!
The CSS :has()
selector has unlocked a bunch of new possibilities to select elements using CSS. A while ago I detailed how you can select elements based on the number of children they have using CSS :has()
. Today we’ll look into using :has()
to select the first, second, …, last element from an “island of elements” that all have a certain class.
~
# The code
If you’re just here for the code, here it is. You can also see the code in action in the demo below.
/* :first-in-island-of-class(.special) – Selects the first element from an island of siblings have a certain class */
.special:first-child,
*:not(.special):has(+ .special) + .special {
…
}
/* :last-in-island-of-class(.special) – Selects the last element from an island of siblings have a certain class */
.special:not(:has(+ .special)) {
…
}
/* :single-in-island-of-class(.special) – Selects the element that forms a single-element island with that a certain class */
*:not(.special):has(+ .special) + .special:not(:has(+ .special)),
.special:first-child:not(:has(+ .special)) {
…
}
If you want to know how these work – along with even more selectors such as a :nth-in-island-of-class(.special)
selector – keep on reading 🙂
~
# Islands?
Before we jump in, let’s make sure we’re using the same lingo here. With “islands of elements” I mean groups of adjacent sibling elements that can be grouped together. For example, consider the following list of child elements:
- no class
.special
.special
.special
- no class
.special
.special
- no class
- no class
.special
- no class
Elements 2, 3,and 4 form an island, as they can be grouped together because they share the same class. Same with elements 6 and 7, they also form an island.
Entry 10 is also an island, even though it only consists of only individual element.
~
# The selectors
Using :has()
, we can detect these islands and style the first and last elements of each island.
Note that the selectors created below all have a rather high specificity. To keep it low, I suggest wrapping them inside a :where()
which nullifies the specificity. If you want to bump up the specificity again, you could tack on a :not()
.
E.g. :where(…):not(.foo)
will have a specificity of (0,1,0)
.
~
:first-in-island-of-class(.special)
This selects the first element from an island of siblings have a certain class. Multiple children in a parent can be selected, as there can be several “islands” of elements with that class.
.special:first-child,
*:not(.special):has(+ .special) + .special {
…
}
*:not(.special):has(+ .special)
first selects all elements that are not .special
but that are followed by a .special
. Using + .special
we then jump from the matched element to its adjacent .special
sibling. To also catch .special
elements that are the first child, .special:first-child
is used.
~
:last-in-island-of-class(.special)
This selects the last element from an island of siblings have a certain class. Multiple children in a parent can be selected, as there can be several “islands” of elements with that class.
.special:not(:has(+ .special)) {
…
}
It works by selecting any .special
that is not directly followed by another .special
.
~
:single-in-island-of-class(.special)
By combining :first-in-island-of-class(.special)
and :last-in-island-of-class(.special)
, it’s possible to detect islands with a class that consist of only 1 element.
*:not(.special):has(+ .special) + .special:not(:has(+ .special)),
.special:first-child:not(:has(+ .special)) {
…
}
~
# Demo
See the Pen by Bramus (@bramus) on CodePen.
~
# More Selectors
We are not limited to only selecting the first or last element in an island. It’s possible to select any element at position n
in an island …
:nth-in-island-of-class(.special)
By adding more + .special
clauses to the selection, it’s possible to select the :2nd-in-island-of-class
, :3rd-in-island-of-class
, etc.
/* :2nd-in-island-of-class(.special) */
.special:first-child:has(+ .special) + .special,
*:not(.special):has(+ .special + .special) + .special + .special {
…
}
/* :3rd-in-island-of-class(.special) */
.special:first-child:has(+ .special + .special) + .special + .special,
*:not(.special):has(+ .special + .special + .special) + .special + .special + .special {
…
}
~
:nth-last-in-island-of-class(.special)
Same goes for a :nth-last-in-island-of-class
selector: add more + .special
clauses to the condition. Then tack an extra :has(+ .special)
onto the selector to jump to the correct element.
/* :2nd-last-child-in-island-of-class(.special) */
.special:not(:has(+ .special + .special)):has(+ .special) {
color: red;
}
/* :3rd-last-child-in-island-of-class(.special) */
.special:not(:has(+ .special + .special + .special)):has(+ .special + .special) {
color: green;
}
~
Selector Generator
Use the pen below to generate :nth-in-island-of-class(.special)
and :nth-last-in-island-of-class(.special)
selectors. Use the dropdowns to change the value for n
as well as the type of selection. The selector is not limited to classes, but is limited to a compound selector.
See the Pen by Bramus (@bramus) on CodePen.
~
# Browser Support
These selectors are supported by all browsers that have :has()
support. At the time of writing this does not include Firefox.
👨🔬 Flipping on the experimental :has()
support in Firefox doesn’t do the trick either. Its implementation is still experimental as it doesn’t support all types of selection yet. Relative Selector Parsing (i.e. a:has(~ b)
) is one of those features that’s not supported yet – Tracking bug: #1774588
~
# Spread the word
To help spread the contents of this post, feel free to retweet its announcement tweet:
Quantity Queries for “islands of elements” with the same class, thanks to CSS `:has()`
🏷 #css #selectors pic.twitter.com/P8HgL5w7li
— Bram.us (@bramusblog) December 13, 2022
~
🔥 Like what you see? Want to stay in the loop? Here's how:
This content originally appeared on Bram.us and was authored by Bramus!

Bramus! | Sciencx (2022-12-13T14:52:03+00:00) Quantity Queries for “islands of elements” with the same class, thanks to CSS :has(). Retrieved from https://www.scien.cx/2022/12/13/quantity-queries-for-islands-of-elements-with-the-same-class-thanks-to-css-has/
Please log in to upload a file.
There are no updates yet.
Click the Upload button above to add an update.