CSS :has() Selector: The Layout Trick I Wish I Knew 5 Years Ago The CSS `:has()` selector, now supported in all major browsers, allows developers to style a parent element based on whether it contains a specific child element, effectively turning CSS into a conditional parent selector. This capability has enabled frontend developers to remove entire JavaScript files and eliminate fragile modifier classes by letting layout and styling respond directly to content structure, such as adapting a card's grid layout based on the presence of an image or applying hero styling to a section containing a primary call-to-action button. CSS :has is not just a fancy :parent When :has started popping up in specs and tweets, I mentally filed it under “cool, but not for shipping work.” I was wrong. Now it is in Chrome, Safari, Edge, and Firefox. I use it in real projects. It has removed entire JavaScript files and a pile of .is-active classes that I was embarrassed to maintain. If you are a working frontend dev, the shorthand is this: :has turns CSS from “style what is there” into “style this thing if it contains that thing”. That one capability changes layout, state, and validation flows. I will walk through three places where it made a real difference for me: - Parent styling without JS - Sibling state UIs without wiring events - Form validation UI that reacts to the DOM, not a framework All of this shipped with zero additional JavaScript. Quick mental model of :has The syntax looks like a pseudo class on a selector: .card:has img.hero { / styles here / } Read it as: “select .card elements that have a descendant img.hero somewhere inside.” It is a conditional filter on the left side of the selector. You can also scope it more tightly: .tabs:has .tab.is-active { / direct children only / } Or use it with relational selectors like siblings: .field:has + .field--error { / this .field is followed by an error field / } Once that clicks, you start seeing places to remove JS. 1. Parent styling in a content-heavy project First real use: a content-heavy marketing site for a biohacking brand I work with. Editors can drop components in any order with a CMS. Sometimes a card has an image, sometimes it is text-only. The layout should adapt. Previously I solved this with modifier classes from the CMS, or a hydration script that scans the DOM and adds classes like .card--with-media . Boring, fragile, and slightly gross. With :has I deleted that script. Image-aware cards The card markup is boring on purpose: