Is there a CSS parent selector?

Is there a CSS parent selector?

Hi Apksha,

The W3C’s Selectors Level 4 Working Draft introduces a powerful pseudo-class, :has(), which allows for selecting elements based on the presence of specific descendants. For example:

li:has(> a.active) { /* styles to apply to the li tag */ }

This selector is widely supported by major browsers. You can check the current browser support for this feature at caniuse.com.

If your target browser does not support this feature, you may need to use JavaScript to achieve similar functionality.

To learn more about CSS Selectors, follow the guide below and get detailed insights.

In the CSS Selectors Level 4 specification, a new selector called :has() is introduced, which allows for selecting parent elements based on their children. This selector is currently supported in Safari and Chrome 105. You can check the full support table here.

Previously, CSS selectors descended the DOM to select elements. For example, to select a <p> tag within a <div> tag, we used:

div p {
  color: red;
}

However, selecting parent elements based on their children was not possible in CSS until the introduction of the :has() selector. This limitation often required the use of JavaScript. The main reason for not implementing parent selectors in CSS was the significant processing overhead it would introduce. CSS is designed to be fast to parse, but selecting parent elements requires more complex processing.

With the :has() selector, we can now select <div> elements that have <p> children, or any other combination of selectors. For example:

div:has(p) {
  color: red;
}

This will make any <div> with a <p> child red.

The :has() selector can also be combined with other selectors. For instance, to select only <div> tags with direct <span> children:

div:has(> span) {
  color: red;
}

The :has() selector is not limited to parent selection. For example, to select a <span> with a sibling <div>:

span:has(+ div) {
  color: red;
}

Or to select an element that does not have a child, using the :not() selector. For example, to select any <div> without a <p> child:

div:not(:has(p)) {
  color: red;
}

One common issue in CSS is that the :empty selector does not select elements that contain only text. The :has() selector allows us to select elements that only contain text nodes and no other child elements. While this is not a perfect solution for elements with spaces, it does provide the ability to select elements with only text nodes, which was not possible before:

div:not(:has(*)) {
  background: green;
}

The CSS parent selector, also known as the :has() selector, has been implemented in Safari TP 137 and is currently being implemented in Chrome as well (MDN Documentation).

Parent selection is achieved using the pseudo-class :has(). For example, div:has(> .child) will select all

elements with a child having a class of child.

Other examples include selecting the direct parent of an element:

<div>
  <p>Child Element</p>
</div>
div:has(> p)

And selecting all the parents of an element:

<div id="grandparent">
      <div id="parent">
            <div id="child"></div>
      <div>
</div>

The following selector will select both grandparent and parent:

div:has(.child)

You can also use it for nested selectors and even with other pseudo-classes:

div:has(> :nth-child(10))

Other valid CSS operators can be used to customize the query.

Keep an eye on caniuse.com/css-has for browser compatibility.