CSS :has() Parent Selector
Tags: css, webdev, design
Published: 2022-10-19 15:01:59

The `:has()` relational pseudo-class is officially recognized as a **Parent Selector**, and in the actual spec \[[Selectors Level 4](https://www.w3.org/TR/selectors-4/#relational)\], it is described as a relative selector that accepts “[forgiving-relative-selector-list](https://www.w3.org/TR/selectors-4/#typedef-forgiving-relative-selector-list)“. However, `:has()` is extremely capable as far as selectors go, and there’s plenty of proof that it is [more than](https://www.bram.us/2021/12/21/the-css-has-selector-is-way-more-than-a-parent-selector/#more-than) just a _parent selector_.

### **Syntax**

The syntax of the `:has()` pseudo-class is relatively simple and easy to learn to get started, because its semantics are very clear and consistent with the rendering presentation, meaning that the so-and-so element will match if it matches the so-and-so selector.

As a simple example, the following function means that if the element has an `<a>` element inside the `<img>` element, the `<a>` element will match.

    a:has(img) { 
      display: block; 
    }

We can use this selector to easily distinguish whether it is a text link or an image link and set different CSS styles.

The `:has()` pseudo-class supports all CSS selectors. E.g.:

    a:has(> img) { 
    display: block; 
    }

The above function indicates that `a` elements whose matching child element is an `img` element will be matched, while more distantly related descendant elements will not be considered.

Note that in the above code, the `:has` pseudo-class argument - `>` selector - is written directly at the top of the argument, rather than `a:has(a > img)`. The `:has()` pseudo-class has an invisible `:scope` pseudo-class at the top of its argument, so it is prohibited to write `a:has(a > img)`.

Similarly, you can use selectors like `+` or `~` to achieve the effect of a "front sibling selector", where the front element is selected based on the back sibling element. Like so:

    h3:has(+ p) { 
    font-size: 1.5rem; 
    }

The above query indicates a match for an `h3` element followed by an `p` element. The `:has()` pseudo-class also supports complex selectors and selector lists. E.g.:

    article:has(h3, p) { 
       background-color: #f3f3f3;
    }

The above query indicates that only `h3` elements or `p` elements inside the article elements will match: as an **or** relationship, not a **with** relationship.

If you want the relationship to be **with**, i.e., both `h3` elements and `p` elements to match, you can write it like so:

    article:has(h3):has(p) { 
       background-color: #f3f3f3; 
    }

The `:has()` pseudo-class can also be mixed with other pseudo-classes, such as `:checked`, `:enabled`, etc., or even with other logical pseudo-classes, such as `:not`. E.g.:

    section:not(:has(h3)) {
      border: 1px solid yellow;
    }
    
    section:has(:not(h3)) {
      color: orange;
    }

_Note that the two queries above have different meanings._

The former selector means that `section` elements that do not contain `h3` elements have a yellow border, while the latter means that `section` elements that contain elements that are not `h3` elements are orange in color.

It is honestly confusing for _everyone_. But once you understand that **not -> has** means _has not_, it gets easier.

### **Examples**

The `:has()` pseudo-class has been available for quite some time now (either under browser flags or with a polyfill), and the possibilities of what this parent selector will be able to do will have to be unraveled over time.

In the meantime, this section covers examples of creative ways in which `:has()` is already being utilized.

**#1: Styling** `figcaption` **only if it is present**

 
![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/n7t1pla037nzcl6sueoa.png)

See the Pen [:has() Demo #1 — Figure variations](https://codepen.io/jensimmons/pen/eYGKNYy) by Jen Simmons ([@jensimmons](https://codepen.io/jensimmons))

**#2: Carousel gallery with scale and gap effect in pure CSS**

 
![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/2ugpjb745f4sxnwm264s.png)

See the Pen [:has() example four](https://codepen.io/kevinpowell/pen/PoeGYGK) by Kevin ([@kevinpowell](https://codepen.io/kevinpowell))

**#3: Creating a native color theme switcher**

 
![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/teysnk6v9w472a61j3g6.png)

See the Pen [CSS :has - Color theme](https://codepen.io/shadeed/pen/OJzoxgo) by Ahmad Shadeed ([@shadeed](https://codepen.io/shadeed))

### **Browser Support**

  ![Data on support for the css-has feature across the major browsers from caniuse.com](https://caniuse.bitsofco.de/image/css-has.jpg)