DEV Community

Cover image for Understanding :has() selector in CSS.
Jasmin Virdi
Jasmin Virdi

Posted on

Understanding :has() selector in CSS.

While working on CSS problems I have come across a situation multiple times where I need to apply styles to parent element only if it has a specific type of child element.
For example -

/* Selects an h1 heading with a
paragraph element that immediately follows
the h1 and applies the style to h1 */
Enter fullscreen mode Exit fullscreen mode

The solution to above problem is using :has() pseudo-class which is also commonly known as parent selector. If we had to do vice versa where styles need to applied to paragraph element(child) we can use > selector.

Let's understand this more in detail with the help of an example.

Suppose we are working on an application which has a page containing multiple figures with and without captions. Let's say we have to apply styles to the figures with captions.

Here we can make use of :has() selector which will help us to identify figure with caption and apply to it.

Syntax for :has() selector is -

:has( <relative-selector-list> )
Enter fullscreen mode Exit fullscreen mode

In order to select the figure element with figcaption I used the following code on css.

figure:has(figcaption){
  apply styles here...
}
Enter fullscreen mode Exit fullscreen mode

Point to note about :has() selector is supported in Firefox behind the layout.css.has-selector.enabled flag.

In order to check the browser compatibility of the :has() selector I have used @supports CSS at-rule to specify the declaration on browser support for this feature.

For this I have wrapped my code around -

@supports(selector(:has(*))) {
    figure:has(figcaption) {
       apply styles here...
    }
}
Enter fullscreen mode Exit fullscreen mode

A fallback logic is a good to have in case if this does not work in any browser due to compatibility issues. We can use JS to select the parent element and apply styles to it after checking the CSS support of :has() feature in the browser.

if (!CSS.supports('selector(:has())')) {
    const galleryFigures = document.querySelectorAll("figure")

    // loop over each HTML figure element to find if figcaption is present
    for (let figure of galleryFigures) {
        console.log(figure.children.length)
        if (figure.children.length === 2) {
            figure.style.height = '18rem';
            figure.style.borderRadius = '10px';
            figure.style.background = 'linear-gradient(to right, #935116, #FAE5D3)'
            figure.style.color = 'white';
            figure.style.backgroundSize = '400% 400%';
        }
    }
}
Enter fullscreen mode Exit fullscreen mode

Conclusion

In this article we have seen the usage of :has() property along with some interesting examples. We also covered its browser compatibility and a fallback logic in case of missing support. Feel free to add more points to this article.

Happy Learning! 👩🏻‍💻

Top comments (7)

Collapse
 
tlylt profile image
Liu Yongliang • Edited

The last code snippet checks for the support of ‘:where’ instead of ‘:has’, is that a typo or…?

Collapse
 
jasmin profile image
Jasmin Virdi

Thanks for pointing out the typo. 🙌

Collapse
 
khejit68 profile image
khejit68
CSS.supports('selector(:has())')
Enter fullscreen mode Exit fullscreen mode

The above snippet returns false in my browser console. I use Opera 94, so :has() selector should be available.
When I write CSS.supports('selector(:has(div))'), console returns true. Do I use it wrong?

Collapse
 
jasmin profile image
Jasmin Virdi

Hi @khejit68 ,

You can check for browser compatibility here.

Collapse
 
khejit68 profile image
khejit68

Uhm, yes. As you can see, Opera 91 and higher is fully compatible. Hence my question.

Thread Thread
 
jasmin profile image
Jasmin Virdi

In the code snippet there is negation in front of CSS.supports('selector(:has())') which will return false if the browser supports the :has() property. In this case the styles from css file will be applied.

I assume in your case the styles from css file is applied ?

Collapse
 
moscosolenin profile image
Lenin Moscoso

Thanks.