Can I :has?

Firefox finally shipped :has in December, which means we can start shipping it in our code. Obviously depending on your users and you probably should consider backwards compatibility and such. But we are going to look at :has optimistically this morning.

So below is a navigation bar like what I use in Selah. You have a selected button and hover states. But the complex part is that the sharps (#) visually select their corresponding whole note button. In the past, this would be complex. You’d need to set a selected state in either a data attribute (e.g. data-selected) or a class as well as the aria-selected on both buttons. Not hard for JS, but more work.

And that brings us to :has. This is a pseudoclass that allows you to match elements on other elements. For instance, if I wanted to select an element with a focused input, I could do this:

.fieldset:has(input:focus) {
    border: 1px solid red;
}

We can look ahead, to pull a term from regular expressions. Onto our navigation bar, we want to show the selected state on a whole-note that is followed by a selected half-note.

.whole-note:has(+ .half-note[aria-selected="true"]) button {}

And we can also do this with :hover selectors, meaning we can say on hover of our half-note, we can show the hover state on the corresponding whole-note.

.whole-note:has(+ li.half-note button:hover) button {}

This is saying:

  1. Get the .whole-note.
  2. Check that it is followed by hovered half-note (:has(+ li.half-note button:hover)).
  3. And get the button for this match.

This changes everything. That’s only a slight exaggeration. Your code is more readable and more concise. You are shipping less code too.

Go, dabble and learn, y’all.

Hey! Did you enjoy what you just read? Like buttons and shares may stoke the ego, but coffee fuels the body. No subscription, just $3.

Buy Me a Coffee!

Other posts you may enjoy!