Despite being a powerful presentational language, CSS has historically been unable to do many things, one of which is having a parent selector. We are thankful for the new pseudo-class :has(), which makes it possible to have a parent selector and does much more than we had expected.
The :has() selector in CSS allows us to style an element based on its descendants. As far as its use case is concerned, it serves not only as a parent selector but is much more than that. We will deep dive into CSS :has() selector in this detailed blog and gain a deeper understanding of it.
So let’s get started!
Web browser compatibility of CSS :has() selector
Whenever you are using a new feature or CSS property, you should ensure that it is compatible with most common browsers. We will examine the browser compatibility of the CSS :has() selector.
Although not available for all browsers, it is available for some of the latest versions of popular browsers, such as Chrome, Edge, and Safari. You can also enable it via the Experimental Web Platform Feature flag in Chrome.
What are CSS Selectors
When styling an HTML element, a CSS selector is used to select that element. HTML elements are chosen using CSS selectors based on their id, class, type, attribute, etc.
CSS selectors can be categorized into one of five groups:
- Simple selectors: It selects the elements based on name, id, and class.
- Combinator selectors: This selector selects elements based on a specific relationship between them.
- Pseudo-class selectors: A pseudo-class selector selects elements based on the current state.
- Pseudo-elements selectors: Pseudo-elements selectors select and style a part of an element.
- Attribute selectors: This selector selects elements based on an attribute or attribute value.
What is CSS :has() selector
The CSS :has() selector, as said, is a pseudo-class elector that helps you to select elements that contain elements that match the selector you pass into the :has() function.
CSS :has() selector syntax
<target_element>: If the condition passed as an argument to :has() pseudo-class has been satisfied, the element targeted by the selector “target_element” will be targeted.
<selector>: A condition defined with a CSS selector that needs to be met for styles to be applied to the selector.
The pseudo-class selector :has() takes a relative selector list as an argument. Any invalid selectors passed as arguments are ignored.
CSS :has() selector examples
Let’s look at an example of selecting all the <div> elements that directly contains <p>
You can see from the example above that we choose the <div> element, which has the <p> element as a child, and then we style it.
Why is CSS :has() selector more than a parent selector
The :has() selector, however, is much more than just a parent selector. You can use a combination of selectors to select a particular element relative to another element.
The relational selector effectively functions as a previous sibling selector because it can target adjacent elements in the DOM tree in addition to the target element’s children and state.
What are the possible arguments for :has() selector
It is possible to pass advanced CSS selectors such as combinator selectors as arguments to the :has() method because the argument list is the selector itself.
There are four different combinators in CSS:
- descendant selector: The descendant selector (space) matches all elements that are children of the specified element.
- child selector (>): The child selector selects all elements that are the children of a specified element.
- adjacent sibling selector (+): The adjacent sibling selector is used to select an element that is directly after another specific element.
- general sibling selector (~): The general sibling selector selects all elements that are the next siblings of a specified element.
Let’s look at an example of matching <h1> elements that are immediately followed by a <p>, i.e. adjacent siblings.
From the example, you can see that h1:has(+p) will select the <h1> element which has an immediate <p> element. Similarly, you can select any element by combining selectors.
Chaining of CSS :has() selector
CSS :has() selector can be chained and then select elements accordingly, and any level of chaining is doable.
In addition to chaining, we can also provide a selector list, and if you ever add something invalid to the list, it will be ignored automatically.
When to use CSS :has() selector
The :has() selector is ideal when we want to select elements based on their content. Typically, the browser’s engine evaluates CSS rules from right to left in order to apply them when we create rules that target HTML elements.
Suppose we want to select an image that is inside the <div> element. We accomplish this using the descendant selector (space):
The above CSS rule will select the image and style it, but what if you encounter a situation where you want to select the <div> element that has the <img> element? In this situation, it is ideal to have a parent selector, i.e, :has() selector.
Another scenario that is ideal for using the :has() selector is when we want to select the previous sibling of an element. This is handy when we want to style form elements like <label> element which is the previous sibling of an input element.
Real World use cases of :has() selector
Let’s look at a few actual examples where the :has() selector will be useful.
In the first example, we’re trying to style the label element in accordance with the input element’s current state. The label’s color will change from blue to red depending on whether the input element has an invalid value.
Here is what the output will be:
You can get the full source code from this codepen.
Another application for the :has() property is to style an element according to the class name that has been given to it. An example related to this is given below.
You can see there is a difference in the middle element because we have given the class name discount to the <div> element and with :has() property, we target the element that has a class name of discount and style it accordingly.
With the help of the aforementioned example, you can see how useful the :has() selector is.
Wrapping It Up!
Congratulations on reaching this far! You’re a fantastic reader!!
In this detailed blog on :has() selector, we looked at how and when to use the :has() selector. We’ve spoken about syntax, customizing, browser support, and much more. Now you know how to style and use :has() selector in the most effective and efficient way.