CSS :has selector

  • CSS

When I first started learning CSS, I quickly realized there was one thing I couldn’t do: style a parent element based on what was inside it. If I wanted that, I had to use JavaScript or add extra classes manually.

Then I found the :has pseudo-class — and it felt like unlocking a hidden superpower. Now CSS can actually “look inside” an element and style it based on its children.

Why It’s a Big Deal

With :has, you can style an element if it contains something specific inside it. For example:

div:has(a) {
  background-color: red;
}

Every <div> with a link turns red. No scripting, no class juggling.

You can even target based on attributes:

div:has(a[href^="https://"])
{
  color: pink;
}

Now you’re only styling <div> elements with secure links.

Combining Powers

The fun starts when you mix it with other selectors. For example:

div:not(:has(p)) {
  border: 1px solid pink;
}

That means “give a border to every div that doesn’t have a paragraph.”

Or get really specific:

li:has(a + span) {
  background-color: pink;
}

That matches list items with a link immediately followed by a span.

Styling by State

One of my favorite tricks:

label:has(input:checked) {
  background-color: pink;
}

That’s all it takes to style a label when its checkbox is checked — no JavaScript listeners needed.

My Take

:has feels like one of those CSS features we’ll look back on and wonder how we lived without. It keeps styling logic where it belongs — in the CSS — and removes a ton of messy DOM manipulation.

It’s not something I use every day, but when the problem calls for it, it’s elegant, declarative, and surprisingly powerful. If you haven’t played with it yet, spin up a CodePen and see what parent-aware CSS can do for you.

CSS :has selector - Mostafa Waleed