The CSS Feature That Finally Let Parents Fight Back

For decades CSS couldn't style parents based on their children. :has() changed that. Now used on 41% of sites, the selector powers focus states, modals, dark mode, and form UX without JavaScript. Industry leaders like Josh Comeau and Daniel Schwarz show how it reshapes stylesheet architecture.
The CSS Feature That Finally Let Parents Fight Back
Written by Sara Donnelly

Developers begged for it for decades. A way to style an element based on what it contained. Not its children. The element itself. The request sat on wish lists since the late 1990s. Browsers said no. Performance concerns. Parsing direction. Too risky.

Then came :has(). And everything changed. Slowly at first. Now it appears on 41 percent of websites. Project Wallace reports that figure from scans of more than 100,000 live sites. Adoption accelerated once Firefox shipped support in late 2023. Today the selector ranks as the most-used and most-loved feature in the State of CSS 2025 report.

Josh Comeau didn’t expect much from it. He builds with React. Complex selectors rarely appear in his work. Yet after rebuilding his own site with modern CSS, he reversed course. “I was wrong about :has,” he wrote. “It’s an incredibly handy utility, even in a CSS-in-JS context.” (Josh W. Comeau, September 2024).

The mechanics feel simple on paper. Write a selector that looks forward or upward instead of down. article:has(h2) targets any article that contains an h2. Style the container differently when it holds specific content. No JavaScript. No extra classes. Pure declaration.

But the implications run deeper. CSS traditionally reads from right to left. The final compound selector determines the subject. Engineers once believed selecting parents would require scanning the entire document tree on every change. Expensive. Slow. :has() arrived with safeguards. Browser teams optimized the implementation. Real-world usage proved acceptable.

Comeau demonstrates the power with focus states. On his bento-box layout, individual cards contain buttons or links. Keyboard navigation triggered awkward outlines on inner elements. The fix? Move the outline to the parent when any interactive child receives focus-visible.

.bento-card:has(button:focus-visible) { outline: 2px solid var(--color-primary); }

He pairs it with a rule that removes the default button outline. An @supports block provides graceful fallback for older browsers. The result feels intentional. Clean. And it preserves semantic HTML. No need to wrap everything in a button tag and break text selection.

Another pattern from the same article proves even more surprising. Global detection. Add a data attribute to any element in the document. Style the html or body tag based on its presence. Comeau uses it to disable scrolling when a modal appears.

html:has([data-disable-document-scroll="true"]) { overflow: hidden; }

The modal component itself stays simple. Toggle the attribute. CSS reacts instantly. No useEffect. No style mutation in JavaScript. The browser handles the rest. “How friggin’ cool is that??” Comeau asks.

Jen Simmons took the idea further. A dark mode toggle with zero JavaScript. One checkbox. One :has() rule on the body that checks whether the checkbox is :checked. Swap CSS custom properties. The technique remains incomplete for production. It ignores system preferences and persistence. Still, the proof of concept stunned developers when she shared it.

By October 2025, Daniel Schwarz could list dozens of patterns in a single article. Parent styling. Previous sibling selection. “Anywhere” effects that blur non-hovered cards across an entire section. Form validation that styles fieldsets or legends when they contain invalid inputs. All without a single line of script. (LogRocket Blog, October 2025).

One example stands out for accessibility. Style a label differently when its associated input sits in an invalid state. Or highlight an entire card when it contains an image. Or adjust grid tracks based on the number or type of children. These adjustments once required resize observers or mutation observers. Now they live in the stylesheet.

Schwarz captures the mindset shift. “Once you start using :has(), you’ll be amazed by how many problems it elegantly solves. After a while, your mindset shifts to, ‘Can I do this with :has() instead?’”

Performance questions linger. Some teams still hesitate on large documents. Yet the State of CSS data suggests most developers no longer worry. Browser engines improved query efficiency. Many uses serve as progressive enhancements anyway. If the rule fails, the page still works.

Browser support now sits near universal for modern users. Safari led. Chrome followed. Firefox completed the picture. The CSS-Tricks coverage of Interop 2026 highlights continued collaboration among engine teams on other features. :has() already benefits from that earlier alignment.

Comeau’s original newsletter from April 2026 never mentioned the selector. It focused instead on AI tools and his new Whimsical Animations course. Yet his separate :has() article from 2024 continues to influence how professionals think about stylesheet architecture. The piece avoids hype. It shows concrete before-and-after code. Developers read it and immediately open their editors.

Real-world impact appears in unexpected places. E-commerce sites style product cards differently when they contain a “sale” badge. Documentation pages adjust layout when code blocks appear. Forms gain contextual help text visibility based on sibling state. Each case removes a small piece of JavaScript that once managed classes or inline styles.

Not every problem disappears. Complex conditional logic still belongs in code. Animation orchestration. Data fetching. Business rules. But for presentation layers that react to content or user interaction within the DOM, :has() removes entire categories of workarounds.

The selector also pairs beautifully with other modern additions. Container queries. Cascade layers. Color functions. Scroll-driven animations. Together they push more behavior into the browser’s native engine. Less custom code. Fewer bugs at the boundary between script and style.

Critics once warned that powerful selectors would lead to unmaintainable CSS. The opposite appears true so far. Rules become more declarative. Intent reads clearly from the stylesheet. A card that changes when it holds an image explains itself. No hidden JavaScript side effects.

Adoption numbers from Project Wallace confirm the trend. Forty-one percent. And climbing. On sites that use it, the selector often appears in multiple places. Teams that try it rarely revert.

Comeau ended his exploration with a bold claim. :has() feels like the missing selector. Relationships that could not be expressed before suddenly become straightforward. Previous siblings. Distant cousins in different branches of the tree. Global flags set anywhere in the document.

The web platform never stops accumulating capability. Some additions spark immediate excitement. Others take years to reveal their true value. :has() belongs in the second group. It looked like a niche trick at first. Then developers started combining it with focus states, form validation, modal behavior, theme switching.

They realized the real power wasn’t selecting parents. It was removing JavaScript from places it never belonged. It was writing styles that respond directly to the live document structure. It was making the browser do more of the work.

That shift matters for teams under pressure to ship faster. For accessibility auditors tired of ARIA hacks. For designers who want visual states tied to content rather than classes. The selector doesn’t solve every frontend problem. But it quietly eliminates dozens of small ones that used to consume hours.

And that, after twenty-five years of waiting, feels like progress worth celebrating.

Subscribe for Updates

AITrends Newsletter

The AITrends Email Newsletter keeps you informed on the latest developments in artificial intelligence. Perfect for business leaders, tech professionals, and AI enthusiasts looking to stay ahead of the curve.

By signing up for our newsletter you agree to receive content related to ientry.com / webpronews.com and our affiliate partners. For additional information refer to our terms of service.

Notice an error?

Help us improve our content by reporting any issues you find.

Get the WebProNews newsletter delivered to your inbox

Get the free daily newsletter read by decision makers

Subscribe
Advertise with Us

Ready to get started?

Get our media kit

Advertise with Us