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.