All articles
CSS reference

The CSS :has() Selector Explained

How the CSS :has() selector lets you style a parent based on its children - the long-awaited parent selector - with practical, real-world patterns.

6 min read - Updated 2026-06-18

:has() is the parent selector CSS lacked for two decades. It matches an element based on what it contains, so you can finally style a container by its children, a label by its input's state, or a card by whether it holds an image - all without JavaScript.

How :has() works

Put a relative selector inside :has() and the element matches when it contains something matching that selector. The match target stays the outer element, not the child.

figure:has(figcaption) - figures that contain a caption

label:has(input:checked) - labels whose input is checked

div:has(> img) - divs with a direct image child

article:has(h2, h3) - articles containing a subheading

Patterns you could not do before

Because :has() reacts to descendant state, it unlocks layout and styling decisions that previously required scripting or extra wrapper classes.

Style a form row that contains an invalid field: .row:has(:invalid)

Add spacing only to cards that include media

Highlight a list item whose link is focused: li:has(a:focus)

Combine with :not() to target containers missing a child

Support and performance notes

:has() is supported in all current major browsers. It is well optimized, but very broad selectors evaluated on large trees are worth sanity-checking.

Baseline-supported in current Chrome, Edge, Safari, and Firefox

Provide a sensible default for very old engines via graceful degradation

Keep the relative selector specific rather than universal

Verify the effect live across breakpoints and states

Release checklist

Replace JS-driven parent classes with :has() where possible.

Keep the inner selector specific for clarity and performance.

Provide fallbacks for browsers without :has().

Test interactive states (:checked, :invalid, :focus) in context.

Frequently asked questions

What does the CSS :has() selector do?

:has() matches an element based on its descendants. It is effectively the parent selector - figure:has(figcaption) styles figures that contain a caption, something CSS could not do natively before :has().

Is :has() supported in all browsers?

Yes, :has() is supported across all current major browsers. For older engines, design a sensible default and treat the :has() styling as an enhancement.

Can :has() check for the absence of an element?

Combine it with :not() - for example article:not(:has(img)) targets articles that do not contain an image. This pairing covers most "only when missing" use cases.

Related guides