
What is :has() in CSS?
:has() is a next-generation CSS selector, often referred to as a “parent selector”.
It allows you to select elements based on what is inside them or nearby.
Previously in CSS, we were able to select child elements (.card img {}), but we could not style the parent if it contained something specific inside. :has() resolves this issue.
It can be used as a replacement for JS in some cases (for example, styling the parent when a child is active).
Syntax
element:has(selector) {
/* styles */
}element— the element to which we apply the rule.selector— the condition for what must be inside.
Real example:
.article:has(h2, h3) {
padding-top: 2rem;
}If the article has subheadings, add extra padding.
Syntax for using has() with multiple conditions
In CSS, you can use :has() with multiple conditions — this is a powerful feature that makes CSS much more “intelligent” and context-dependent. Support for :has() has appeared in most modern browsers.
The :has() selector can take one or multiple conditions, separated by commas or logical operators:
OR (A, B) — works like “or”
article:has(h1, h2) { border: 1px solid red; }Will apply the style to <article> if it contains either h1 or h2, or both.
AND (A:has(B):has(C)) — works like “and”
To set multiple conditions at once, you need to nest :has():
div:has(h1):has(p) { background: lightgreen; }Will apply the style to <div> if it contains both h1 and p.
Complex conditions with nesting
section:has(article:has(img)) { outline: 2px dashed blue; }Will apply the style to <section> if it contains an <article>, and within it — an <img>.
Combining with pseudo-classes
form:has(input:invalid) { border: 2px solid red; }Will apply the style to <form> if it contains at least one invalid <input>.
N.B.
Selectors with :has() can be heavy on performance, especially when used on large pages. The browser has to scan the contents of each element to determine whether to apply the style.