A Simple CSS Selector That Most Devs Never Try - the :has() Selector

If you ask a group of developers: “Hey, have you used :has() before?”
Most of them will look at you like: “Bro, is that even real CSS?”

Yes. It is real. It is powerful. And honestly… it feels a bit illegal because CSS is not supposed to be this smart. But here we are.

Today I want to share this “new old” CSS superpower that can change how you build UI logic — without JavaScript. And trust me, you will feel like a magician.


What Is :has()?

The official definition is something like:

“Select an element if it contains something that matches the selector inside.”

But in simple language:
:has() is the closest thing we have to a “parent selector” in CSS.

With :has(), you can style a parent based on what the child looks like.

Something like:

.card:has(img) {
  border: 2px solid blue;
}

Boom.
If .card contains an <img>, it becomes blue.
CSS just checked the inside and reacted.


Why It Feels Like CSS With Superpowers

Before :has(), CSS always felt like working with strict Vietnamese parents:

  • You can look at your children (descendant selectors)

  • But you cannot look at your parents

  • No arguments, no exceptions :))

But now :has() says:
“Don’t worry bro, I can look up, I can look down, I can check neighbors— I handle everything.”

Here are some things you can suddenly do:

  1. Style a form when an input is invalid

No JS. No event listener. Just CSS.

form:has(input:invalid) {
  border: 2px solid red;
}

Boom. Instant feedback UI.

2. Change button style when a checkbox is checked

Classic “Enable button when user agrees”.

button:has(+ input:checked) {
  background: green;
}

3. Accordion without JavaScript

Yes, you read that right.

.item:has(.content.open) {
  max-height: 200px;
}

A Real Example (Dev-Friendly)

Let’s say you want to highlight a .product-card only when it has .sale-tag.

.product-card:has(.sale-tag) {
  background: #fff7e6;
  border-color: orange;
}

Result:
When the sale tag appears → whole card becomes “on sale mode”.

And you didn’t write even one line of JavaScript.
Feels good right?


Browser Support?

Good news:

  • Chrome ✔

  • Safari ✔

  • Edge ✔

  • Firefox ✔


Why Most Devs Don’t Use It Yet

Because:

  • They don’t know

  • They think it’s not supported

  • They heard about it once but forgot

  • CSS scares them

  • That mindset of "Just use JavaScript, it’s faster."

But once you try :has(), you will realize it’s the missing piece we always wanted.


When Should You Use :has()?

Use it when you want CSS to react to the structure of the HTML.

Great for:

  • Forms

  • Cards

  • Interactions

  • Accordions

  • Navigation menus

  • Any “state” that depends on children

Not great for:

  • Complex app logic

  • Heavy UI state (JS vẫn làm tốt hơn)


Final Thought

The :has() selector is honestly a game changer.
It’s like the day you learned Flexbox or Grid for the first time — your brain expands a little bit.

With :has() you can:

  • Style based on children

  • Create UI states without JS

  • Make smarter components

  • Reduce code complexity

  • Make CSS fun again

So next time you code UI, give this selector a try.
Maybe you'll feel like a CSS wizard for 5 minutes.
Worth it.