Selecting parent elements without JavaScript
Selecting a parent based on its children used to require JavaScript. :has() handles it in pure CSS, no event listeners needed.
2document.querySelectorAll('input')
3 .forEach(input => {
4 input.addEventListener('invalid', () => {
5 input.closest('.form-group')
6 .classList.add('has-error');
7 });
8 });
2 border-color: red;
3 background: #fff0f0;
4}
5/* Pure CSS. Zero JavaScript. */
No JavaScript needed
Eliminates an entire class of DOM-manipulation code. Fewer event listeners, fewer bugs.
Instant response
Browser applies styles in the rendering pipeline, no waiting for JS execution or reflow.
Composes naturally
Chain with other selectors: .nav:has(.dropdown:hover), body:has(dialog[open]).
How it works
:has() is a relational pseudo-class. When you write .card:has(img), it selects any .card that contains an img as a descendant. It's the parent selector that CSS lacked for 25 years.
You can use any selector inside :has(): pseudo-classes like :invalid, :checked, :hover, or even combinators like :has(> .direct-child). It unlocks conditional styling that previously required JavaScript.