CSS :has() Selector - The Parent Selector Explained

Learn CSS :has(), the long-awaited parent selector. Target elements based on their children or descendants. Browser support, specificity, and practical examples for modern CSS.

Pseudo-classes

Detailed Explanation

The :has() Relational Pseudo-class

The :has() selector is one of the most powerful additions to CSS. It selects elements that contain a descendant (or sibling) matching the argument selector. This effectively gives CSS a "parent selector" capability that developers requested for decades.

Syntax

parent:has(child) {
  /* styles applied to the parent */
}

Basic Examples

Style a card that contains an image:

.card:has(img) {
  padding: 0;
  overflow: hidden;
}

Style a form group with an invalid input:

.form-group:has(input:invalid) {
  border-left: 3px solid red;
}

Style a nav item that has a dropdown:

.nav-item:has(.dropdown) {
  position: relative;
}

Advanced Patterns

Style preceding sibling (with + combinator inside :has):

/* Label before a required input */
label:has(+ input:required)::after {
  content: " *";
  color: red;
}

Responsive quantity queries:

/* Style differently when list has more than 3 items */
ul:has(li:nth-child(4)) {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
}

Browser Support

  • Chrome 105+ (Aug 2022)
  • Safari 15.4+ (Mar 2022)
  • Firefox 121+ (Dec 2023)

Specificity

The specificity of :has() is determined by its most specific argument, just like :is().

Performance Considerations

Because :has() can evaluate descendants, browsers had to implement efficient invalidation algorithms. In practice, performance is good for typical use cases, but avoid deeply nested or overly broad patterns like :has(*).

Use Case

The :has() selector revolutionizes CSS by enabling parent-based styling without JavaScript. Common use cases include styling form groups based on input state, cards with or without images, navigation items with dropdowns, containers based on empty state, and responsive layouts that adapt to the number of children. It is one of the most impactful CSS features added in recent years.

Try It — CSS Selector Reference

Open full tool