Day 91: a previous sibling selector with :has()
posted on
It’s time to get me up to speed with modern CSS. There’s so much new in CSS that I know too little about. To change that I’ve started #100DaysOfMoreOrLessModernCSS. Why more or less modern CSS? Because some topics will be about cutting-edge features, while other stuff has been around for quite a while already, but I just have little to no experience with it.
I’ve already shown much appreciation for the :has()
pseudo-class in this series, but that we can use it as a previous sibling selector tops it all of.
Since this is not an official selector, but more something like a hack, it can be hard to read and interpret. So, let’s start nice and easy.
We have three buttons. If we hover/focus one button and we want to highlight it and the next adjacent button in the DOM at the same time, we can use the adjacent sibling selector.
button {
outline-width: 8px;
outline-offset: 4px;
outline-color: hotpink;
}
button:is(:hover, :focus-visible) {
outline-style: solid;
}
button:is(:hover, :focus-visible) + button {
outline-style: dashed;
}
There's no previous item selector, but using :has()
we can select an item that comes before another item. I've written about next-sibling combinators and :has()
on day 26. Here’s an example from that post: The following code sets the block-end margin of all <h2>
to 0 if they're followed by a <time>
element.
h2 {
margin-block-end: 0.7em;
}
h2:has(+ time) {
margin-block-end: 0;
}
<h2>Heading</h2>
<p>Teaser text</p>
<h2>Heading</h2>
<time>31.10.2022</time>
<p>Teaser text</p>
Heading
Teaser text
Heading
Teaser text
If we want to use this in our button example, we have to select a <button>
followed by a <button>
in the :hover
or :focus-visible
state.
button:is(:hover, :focus-visible) {
outline-style: solid;
}
button:is(:hover, :focus-visible) + button {
outline-style: dashed;
}
button:has(+ button:is(:hover, :focus-visible)) {
outline-style: dotted;
}
If we have more buttons and we want to select the button that comes before the previous button, we can extend our selector.
button:has(+ button + button:is(:hover, :focus-visible)) {
/* styles */
}
What a beauty!
Here are a couple of other demos:
See the Pen Day 91: previous sibling selector with :has() #100DaysOfMoreOrLessModernCSS by Manuel Matuzovic (@matuzo) on CodePen.
See the Pen selecting previous item using CSS by pourya (@pouriversal) on CodePen.
See the Pen BUBBLE (previous siblings!) by Chris Coyier (@chriscoyier) on CodePen.
Further reading
Overview: 100 Days Of More Or Less Modern CSS