We can use :has, finally!
Tags: css, api, has, parentselector
Published: 2023-06-19 11:05:21

For years, CSS developers have wished for the ability to select an element based on its content. Although CSS provides selectors that can select elements based on a lot of characteristics, until recently there was no way to select an element based on what it contained.

Fortunately, the introduction of `:has()` changed this. This new feature is a *game-changer*, as it allows you to select an element based on its content.

In this post, we’ll dive into one of the most anticipated CSS features: the `:has` pseudo-class. And it turns out to be much more than “just” a parent selector.

## The Syntax

The `:has` pseudo-class is used to select elements based on their contents. It is applied to the element we want to apply rules to, and we pass it to the selector of the element it should contain:

```css
/* Here we target any element with the */
/* class `post` containing an `h1` */
.post:has(h1){
	background-color: teal;
}
```

## Using `:has` as a parent selector

Using `:has` as a parent selector can simplify many situations. Here are some examples that come to mind:

* On some pages of your app, you may want to change the global font size or background color of the `body` element. Previously, before the `:has` pseudo-class was introduced, we would have needed the backend to toggle some HTML class based on the page type. However, with a parent selector, this is now trivial:

  ```css
  body:has(.container.legal-mentions) {
  	font-size: 80%;
  }
  ```
* On our list of blog posts, we want posts to change not have margin if the post contains an image:

  ```css
  .post:has(img){
  	margin-left:0;
  }
  ```

This is extremely powerful in itself, but we can do even more when using *combinators*.

## Going further with Combinators

> Combinators combine other selectors in a way that gives them a useful relationship to each other and the location of content in the document.
> — [MDN](https://developer.mozilla.org/en-US/docs/Learn/CSS/Building_blocks/Selectors/Combinators)

We can use the **child combinator** `>` inside `has` to ensure that we are selecting a direct child element. For example, to select a `div` element that has a `hr` element as a direct child, we can use the selector `div:has(>hr)`.

We can use the **adjacent sibling combinator** `+` to target an element followed by another element. For example, to select a title followed by a subtitle, we can use `title:has(+.subtitle)`.

## Combining with other Pseudo-classes

Changing the style of a container when hovering over a child element sounds pretty cool, doesn't it?

We can achieve this by combining `has` with `hover`. For example, if we want a container to have a border whenever one of its links is hovered, we would use the following code:

```css
.container:has(a:hover){
	border: 2px solid pink;
}
```

## Browser support

As of June 2023, the `:has` pseudo-class is missing only in Firefox. However, it is behind a flag, so it should be supported soon!

![Screenshot of caniuse for the has feature](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9gkj2uhhsoh84wbkh0jv.png)

## Conclusion

The `:has` pseudo-class is a powerful addition to the CSS selector arsenal. It allows you to select elements based on their contents, which can simplify many situations and make your code more maintainable. By using combinators, you can further refine your selections and achieve even more advanced effects.

While it is still missing in Firefox, it is expected to be supported soon. As always, make sure to test your code in all major browsers before deploying it to production.

Thanks for reading, and happy coding!

 Learn how to use combinators and other pseudo-classes to achieve even more advanced effects.

### Sources and Links

* <https://developer.mozilla.org/en-US/docs/Web/CSS/:has>
* <https://webkit.org/blog/13096/css-has-pseudo-class/>
* <https://blog.logrocket.com/how-when-use-css-has-selector/>
* <https://css-tricks.com/the-css-has-selector/>

***I'm Tom Quinonero, I write about design systems and CSS, [Follow me on twitter](https://twitter.com/tomquinonero) for more tips and resources 🤙***