2 min read

CSS :has() Pseudo-class

The :has() pseudo-class represents an element if any of the selectors passed as parameters match at least one element relative to it. It is often referred to as the "parent selector" because it allows you to style a parent element based on the presence or state of its descendants.

1. The Concept

For years, CSS could only look "down" the DOM tree (selecting children based on parents). :has() allows us to look "ahead" or "down" to style the current element.

Syntax: selector:has(relative-selector)

2. Selecting a Parent

This is the most common use case.

/* Selects any <figure> that contains a <figcaption> */
figure:has(figcaption) {
  background: <a href='/?search=%23f0f0f0' class='obsidian-tag'>#f0f0f0</a>;
  padding: 10px;
}

/* Selects any <div> that contains an <img> */
div:has(img) {
  border: 1px solid black;
}

3. Selecting Based on State

You can style a container based on the state of its children.

/* Style a form group if the input inside is invalid */
.form-group:has(input:invalid) {
  border-left: 4px solid red;
}

/* Style a label if the checkbox inside is checked */
label:has(input:checked) {
  background-color: lightgreen;
  font-weight: bold;
}

4. Selecting Previous Siblings

While + and ~ select following siblings, :has() combined with + can select previous siblings.

/* Selects an <h1> only if it is immediately followed by a <p> */
h1:has(+ p) {
  margin-bottom: 0;
}

5. Specificity

The specificity of :has() is equal to the specificity of the most specific selector in its argument list (similar to :is()).

/* Specificity of <a href='/?search=%23child' class='obsidian-tag'>#child</a> is (0, 1, 0, 0) */
/* So div:has(#child) has specificity (0, 1, 0, 1) */
div:has(#child) {
  color: red;
}

programming/css/css programming/css/selectors programming/css/is-and-where-pseudo-classes