Understanding the CSS parent selector :has()


CSS is a powerful language but there are many things it has been unable to do all this while. However, now, with the introduction of CSS :has() pseudo-class, it will now be able to perform most of those actions easily. It is one of the most exciting, rather awaited features introduced in CSS.

So, let’s learn about :has() selector.

Need

According to CSS rules, the child element is targeted based on the parent element (from right to left). In the following example, <button> is the targeted element inside the <div> element and CSS property background: red is applied to <button>.

  div button {
    background: red;
  }

Now, what if we want to target the <div> element which contains <button> element? Well, we can do that now with the help of :has() selector.

The easiest way to describe :has() is as a parent selector. If we wish to target the parent element based on the content or the child element we can use :has().

Syntax

The :has() represents an element if the selector passed as parameter matches the element inside <target> element.

<target>:has<selector>

Example

Let’s consider the same example to understand the :has() selector. In the following example, using the :has() selector, we are targeting the <div> element that has the <button> element.

  div:has(button) {
    background: red
  }

Here, <div> is the targeted element and <button> is the selector, which means CSS property background:red is applied to <div> only if it contains <button> element.

Real world scenario

So, let’s say we have a list of products and some of the products are available with offers. Suppose we want to apply some extra style to products with offers.

<div class="Container">
    <div class="product">
      <h1>Product 1</h1>
        <h3>$130</h3>
      <button class="buy">Buy</button>
    </div>
    <div class="product">
      <h1>Product 2</h1>
      <h3>$130</h3>
      <button class="buy">Buy</button>
    </div>
    <div class="product">
      <h1>Product 3</h1>
      <h3>$100</h3>
      <button class="offer">Apply offer</button>
    </div>
</div>

As shown in the above code, we have 3 products and one of them comes with an offer, Now, we need to apply some extra CSS to that specific product. Generally, we use JQuery or JavaScript to achieve this scenario as shown below.

<script>
  const products = document.getElementsByClassName("product");
      for (let i = 0; i < products.length; i++) {
        let isOffer = products[i].getElementsByClassName("offer");
        if (isOffer[0]) {
          products[i].style.border = "2px solid green";
          products[i].style.boxShadow = "5px 5px 10px lightgreen";
        }
      }
</script>

It is exciting that we can avoid the use of any JavaScript or JQuery and simplify the above code by using :has() selector.

  .product:has(button.offer) {
    border: 2px solid green;
    box-shadow: 5px 5px 10px lightgreen;
  }

Here, if the selector button.offer passed as a parameter matches the element inside product, only then the above CSS is applied.

Only Product 3 matches this condition, as shown in the image below.

Limitations

Although :has() works like magic, there are some restrictions.

  • We can’t :has() a :has().
  :has(.x:has(.y)) {  }
  • We can not use psudeo elements within :has().
  :has(::after) {  }
  • Use of :visited will always be false.
  :has(:visited) {  }

Browser Compability

To check the browser compatibility, we can visit this link.

  • Currently, only the latest versions of Safari support :has() selector by default.
  • We can enable :has() on the latest versions of Chrome by enabling the Experimental Web Platform features.
  • We can enable :has() on latest versions of Firefox using layout.css.has-selector.enabled flag.

We can follow this link to understand better how to enable :has() in Chrome.

Join Our Newsletter