The parent selector CSS never had
For decades, CSS could only select elements based on their ancestors, not their children. You could style a parent that contained a certain kind of child — but only in your head. In the stylesheet, you were powerless.
Developers hacked around this with JavaScript: listen for an event, walk the DOM, add a class to the parent, style that class. Three steps to do something that should be one.
:has() ended that. It lets any selector look inside itself — at its children, its descendants, even what follows it in the DOM. The colon-has pattern unlocks parent selection, sibling-based logic, and state-driven composition that used to require a full framework.
The form above proves it. Every label recolor, every fieldset highlight, every button state change, and the final completion celebration — all triggered by :has(). Not one event listener.
Core patterns
Parent selection
Style a container based on what it contains.
State-driven forms
React to input state without JavaScript.
Sibling-based logic
Combine :has() with :not() and :checked for complex UI states.
Real-world use cases
What :has() replaced three JavaScript patterns with one CSS rule.