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 */
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> )
In order to select the figure element with figcaption I used the following code on css.
figure:has(figcaption){
apply styles here...
}
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...
}
}
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%';
}
}
}
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)
The last code snippet checks for the support of ‘:where’ instead of ‘:has’, is that a typo or…?
Thanks for pointing out the typo. 🙌
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?
Hi @khejit68 ,
You can check for browser compatibility here.
Uhm, yes. As you can see, Opera 91 and higher is fully compatible. Hence my question.
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 ?
Thanks.