1

Day 91: a previous sibling selector with :has()

 1 year ago
source link: https://www.matuzo.at/blog/2023/100daysof-day91/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

Day 91: a previous sibling selector with :has()

posted on January 30., 2023

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

31.10.2022

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 on CodePen.

Further reading

Want more?

Overview: 100 Days Of More Or Less Modern CSS

My blog doesn't support comments yet, but you can reply via e-mail.


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK