CSS if parent has class

The CSS

let el = document.querySelector(".someElement"),
    elParent = null

if(el) {
  elParent = el.parentNode
}
1 pseudo-class has been one of the most-awaited features for years. It’s a level 4 CSS selector, now available as a fully supported feature in Chrome 105 onwards, and will likely become a regular feature soon on other browsers as well.

The

let el = document.querySelector(".someElement"),
    elParent = null

if(el) {
  elParent = el.parentNode
}
1 in CSS is a relational pseudo-class allows you to check if a given element contains certain child elements, select it if any match is found, and then style it accordingly.

This article explains the need for the

let el = document.querySelector(".someElement"),
    elParent = null

if(el) {
  elParent = el.parentNode
}
1 selector, its general usage, various applications and use cases from simple to advanced, browser compatibility, and the fallbacks.

Contents

Why is the let el = document.querySelector(".someElement"), elParent = null if(el) { elParent = el.parentNode } 1 selector necessary?

Most developers rely on JavaScript for certain features CSS does not support by default. However, web browsers today are more powerful than ever, which is opening doors to many new and interesting CSS features.

The

let el = document.querySelector(".someElement"),
    elParent = null

if(el) {
  elParent = el.parentNode
}
1 selector is one such feature. It works on the parent rather than children, and uses a comma-separated list of selectors as arguments, then looks for matches among the children of the element it’s representing. Its functionality is similar to the jQuery
let el = document.querySelector(".someElement"),
    elParent = null

if(el) {
  elParent = el.parentNode
}
9 method.

Let’s go over some of the general needs for the

let el = document.querySelector(".someElement"),
    elParent = null

if(el) {
  elParent = el.parentNode
}
1 selector in frontend development that explain why this feature was in such high demand for years.

First is the possibility to check whether an element contains certain other elements or not, and then styling it accordingly. JavaScript was the only way to do this before, as you can see here:

let content = document.querySelector("#content"),
    headings = [] 

if(content) {
  headings = content.querySelectorAll("h1, h2, h3")
}

if(headings.length) {
  // do something
}

In the code above, we have used

let el = document.querySelector(".someElement"),
    elPs = null

if(el) {
  elPs = el.previousElementSibling
}
1, which is a Web API method to check a division element for headings. The method returns a NodeList of the supplied elements.

An empty NodeList would mean there are no elements present in the immediate parent. An implementation of the above can be found here. Or, you can .

Second is the capability to select the parent element from the children. Again, in lack of a CSS facility to do so, developers have relied on Web API’s parentNode property:

let el = document.querySelector(".someElement"),
    elParent = null

if(el) {
  elParent = el.parentNode
}

View a CodePen demo of the code above here, and .

Finally, there is the ability to select the previous sibling of a given element. The sibling selector in CSS allows you to select the next sibling, but there was no CSS-only way to select previous siblings. The JavaScript implementation looks like this (view a CodePen demo here):

let el = document.querySelector(".someElement"),
    elPs = null

if(el) {
  elPs = el.previousElementSibling
}

You can see how to perform this action with .

Everything we did above with JavaScript can now be achieved with CSS

let el = document.querySelector(".someElement"),
    elParent = null

if(el) {
  elParent = el.parentNode
}
1. We will cover them one by one in the next section after learning how to enable and test this feature on Google Chrome.

Enabling support for the let el = document.querySelector(".someElement"), elParent = null if(el) { elParent = el.parentNode } 1 selector

If you are on an older Chrome version (v.101-104), you can enable this feature from Chrome flags. Make sure you have Chrome 101+ and navigate to chrome://flags from the browser’s address bar.

Set the Experimental Web Platform features to Enabled and you’re good to go. Relaunch the browser and you can work with CSS

let el = document.querySelector(".someElement"),
    elParent = null

if(el) {
  elParent = el.parentNode
}
1 in your Chrome browser.

CSS if parent has class
CSS if parent has class

What does the CSS let el = document.querySelector(".someElement"), elParent = null if(el) { elParent = el.parentNode } 1 selector do?

Let’s explore the

let el = document.querySelector(".someElement"),
    elParent = null

if(el) {
  elParent = el.parentNode
}
1 pseudo-class, its usage, and properties. Because it’s a pseudo-class, it can be attached to any selector with a colon and accepts classes, IDs, and HTML tags as parameters.

The below code explains its general usage and syntax. The class

.selector:has(.class) { ... }
.selector:has(#id) { ... }
.selector:has(div) { ... }
0 only gets selected if it contains the elements passed to it as parameters using the
let el = document.querySelector(".someElement"),
    elParent = null

if(el) {
  elParent = el.parentNode
}
9 pseudo-class:

.selector:has(.class) { ... }
.selector:has(#id) { ... }
.selector:has(div) { ... }

Chainability

You can chain multiple

let el = document.querySelector(".someElement"),
    elParent = null

if(el) {
  elParent = el.parentNode
}
1 pseudo-classes one after the other whenever you see fit. The code below demonstrates how this chaining works:

.selector:has(div):has(.class):has(#id) {
  ...
}

Argument list for multiple selections

You can also provide a list of multiple element selectors, similar to chaining, but much more efficient:

.selector:has(div, .class, #id) {
  ...
}

Flexibility

Suppose you accidentally provided an invalid element selector to the

let el = document.querySelector(".someElement"),
    elParent = null

if(el) {
  elParent = el.parentNode
}
1 pseudo-class. It is intelligent enough to ignore that and consider only the valid selectors:

.selector:has(div, accordion, .class, ::lobster, #id) {
  ...
}

.selector:has(.class) { ... }
.selector:has(#id) { ... }
.selector:has(div) { ... }
4 and
.selector:has(.class) { ... }
.selector:has(#id) { ... }
.selector:has(div) { ... }
5 are invalid selectors and will be ignored in the above case. You’ll see no CSS errors or alerts in the developer tools.

Usage scenarios

Let’s take a look at some example scenarios in which CSS’

let el = document.querySelector(".someElement"),
    elParent = null

if(el) {
  elParent = el.parentNode
}
1 selector comes in handy.

Selecting the parent

This may be the most common use of the

let el = document.querySelector(".someElement"),
    elParent = null

if(el) {
  elParent = el.parentNode
}
1 selector, because its default behavior is to select something if it contains a specific set of elements. But what if we are aware of only the child element?

The universal selector (

.selector:has(.class) { ... }
.selector:has(#id) { ... }
.selector:has(div) { ... }
8) can be used here with
let el = document.querySelector(".someElement"),
    elParent = null

if(el) {
  elParent = el.parentNode
}
1 and the child combinator (
.selector:has(div):has(.class):has(#id) {
  ...
}
0) to quickly select the parent without even knowing anything about it.

Selecting the parent from child with CSS has()

No Description

Checking for multiple children

As discussed in the properties segment above,

let el = document.querySelector(".someElement"),
    elParent = null

if(el) {
  elParent = el.parentNode
}
1 allows you to pass a list of multiple entities, which means you can check for as many selectors as you want within a given element.

Checking for multiple element with CSS has()

Lorem ipsum dolor sit amet consectetur adipisicing elit. Ab pariatur, obcaecati accusantium alias minus repellat itaque amet libero corrupti maiores consectetur quasi! Eligendi ratione eaque et tenetur assumenda neque reprehenderit. Unde, nemo cumque molestiae mollitia impedit voluptate quisquam laborum ut, vitae aliquid totam numquam possimus dignissimos beatae quos corporis alias quod magnam quidem.

 

Selecting the previous sibling

The selection of the previous sibling is made possible by combining the CSS adjacent sibling combinator with the

let el = document.querySelector(".someElement"),
    elParent = null

if(el) {
  elParent = el.parentNode
}
1 pseudo-class.

As you may already know, the adjacent sibling combinator selects the very next sibling of a given element. We can use this behavior with

let el = document.querySelector(".someElement"),
    elParent = null

if(el) {
  elParent = el.parentNode
}
9 to get the previous sibling. Simply put, if an element has a next sibling, it’s easy to select it with
let el = document.querySelector(".someElement"),
    elParent = null

if(el) {
  elParent = el.parentNode
}
1 and
.selector:has(div):has(.class):has(#id) {
  ...
}
5 combinator!

CSS :has() – Selecting Previous Sibling

No Description

Conditional decorations

Styling things with and without certain child elements separately can be avoided with the

let el = document.querySelector(".someElement"),
    elParent = null

if(el) {
  elParent = el.parentNode
}
1 selector. Figure element with and without a caption is the perfect example here.

Conditional figure decoration with CSS :has()

No Description

What if a

.selector:has(div):has(.class):has(#id) {
  ...
}
7 element is there, but doesn’t contain any text? In that case, we can use the
.selector:has(div):has(.class):has(#id) {
  ...
}
8 and
.selector:has(div):has(.class):has(#id) {
  ...
}
9 selectors to keep a check on the content.

Similar to figure decoration, we can easily switch the text alignment of block quotes with more than one paragraph. See it in action here.

Styling empty states

We already have a pseudo-class called

.selector:has(div):has(.class):has(#id) {
  ...
}
9 for styling elements that contain nothing. As far as targeting an empty state is concerned, it does not work as expected. One space inside is enough for it to recognize an element as non-empty.

It’s not ideal to use

.selector:has(div):has(.class):has(#id) {
  ...
}
9 in this case. Let’s create a card grid that also contains a few contentless cards. We’ll be styling the empty card states with the
let el = document.querySelector(".someElement"),
    elParent = null

if(el) {
  elParent = el.parentNode
}
1 selector.

Styling Empty States with CSS :has()

No Description

Type and block adjustments

While styling for an article, keeping type and block elements aligned is a tricky job. Consider an example of mixing code blocks, figures, and block quotes with the general type elements.

The block elements should have more vertical spacing and decorations to stand out among different typographical entities. Here’s some CSS to handle that.


CSS if parent has class
CSS if parent has class

Over 200k developers use LogRocket to create better digital experiences

CSS if parent has class
CSS if parent has class
Learn more →


p {
  margin: 0;
}

p:not(:last-child) {
  margin-bottom: 1.5em;
}

h1,
h2,
h3,
h4,
h5,
h6 {
  line-height: 1.3;
  margin: 1.5em 0 1.5rem;
  color: #111;
}

pre,
figure,
blockquote {
  margin: 3em 0;
}

figcaption {
  margin-top: 1em;
  font-size: 0.75em;
  color: #888;
  text-align: center;
}

The snippet above will produce uneven vertical spacing between headings and block elements, as shown here. But it is possible to make up for these irregularities using the previous sibling selection hack.

Type and Block adjustments using CSS :has()

Lorem, ipsum dolor sit amet consectetur adipisicing elit. Fugit corrupti perferendis quod laborum explicabo ratione quidem laudantium officia odit vitae, quisquam ullam aliquid voluptate consequatur eos quis ducimus, repellat aperiam. Hic tenetur modi explicabo itaque incidunt, obcaecati fugiat consequuntur asperiores aliquid, eius, atque ullam unde. Aut et molestias eaque repudiandae!

Iconized CTAs

Suppose you are creating a CTA or button component in CSS with two variations: the first one is the default, plain button, and the second one is with an icon.

Now, if you are planning to write two separate classes for that, it can be easily avoided with the

let el = document.querySelector(".someElement"),
    elParent = null

if(el) {
  elParent = el.parentNode
}
1 selector. The catch is to simply check the
.selector:has(div, .class, #id) {
  ...
}
4 element for a
.selector:has(div, .class, #id) {
  ...
}
5 child and then style accordingly.

Simple Iconized CTAs with CSS :has()

No Description

Layout adjustments

Let’s say you have two layout variations for a header component: one is the fixed-width, and the other one is liquid, of course.

To keep the contents of the header within a fixed width, we have to add a content wrapper element inside it. The only difference between the markup of these two header versions is the wrapper element.

We can then pair the

let el = document.querySelector(".someElement"),
    elParent = null

if(el) {
  elParent = el.parentNode
}
1 with
.selector:has(div, .class, #id) {
  ...
}
7 selector and add the CSS classes, as shown in the below demonstration.

Wrapper adjustments with :has()

No Description

Another example of adjusting the layout can be modifying the number of columns in a grid as soon as they reach a certain number.

This can be handy when you are not using the

.selector:has(div, .class, #id) {
  ...
}
8 function that determines the best width to fit a column in its grid.


More great articles from LogRocket:

  • Don't miss a moment with The Replay, a curated newsletter from LogRocket
  • Learn how LogRocket's Galileo cuts through the noise to proactively resolve issues in your app
  • Use React's useEffect to optimize your application's performance
  • Switch between multiple versions of Node
  • Discover how to animate your React app with AnimXYZ
  • Explore Tauri, a new framework for building binaries
  • Compare NestJS vs. Express.js

Adjusting Grid according to the number of items with CSS :has()

No Description

As you can see above, the grid automatically adjusts to three columns as soon as it exceeds the mark of two items.

Better form usability

Interactivity is best defined when it’s properly connected to feedback. When it comes to interactive HTML forms, offering the user feedback about its input is the best thing you can do.

With the help of the

let el = document.querySelector(".someElement"),
    elParent = null

if(el) {
  elParent = el.parentNode
}
1,
.selector:has(div, accordion, .class, ::lobster, #id) {
  ...
}
0, and
.selector:has(div, accordion, .class, ::lobster, #id) {
  ...
}
1 pseudo-classes, we can make our forms a lot more dynamic, and with no JavaScript involved.

Interactive HTML Form with CSS :has()

No Description

Checking for browser support

The above-discussed examples show an error dialog if no support to the

let el = document.querySelector(".someElement"),
    elParent = null

if(el) {
  elParent = el.parentNode
}
1 selector is found. This can be done using the
.selector:has(div, accordion, .class, ::lobster, #id) {
  ...
}
3 CSS rule, as shown in the below code snippets:

@supports (selector(:has(*))) {
  .selector:has(...) {
    ...  
  }
}

Above is the progressive way to check for support and style the element as required. If a codebase uses some new features directly, here’s a way to write the backward-compatible versions of the same:

@supports not (selector(:has(*))) {
  .selector {
    ...  
  }
}

The same can also be used to prompt the user if no support was found.

You can also use the Support API in JavaScript to detect the browser support for different features. Here’s an example of that checking for

let el = document.querySelector(".someElement"),
    elParent = null

if(el) {
  elParent = el.parentNode
}
1 support purely in JavaScript:

let el = document.querySelector(".someElement"),
    elParent = null

if(el) {
  elParent = el.parentNode
}
0

Conclusion

In the article above, we learned about

let el = document.querySelector(".someElement"),
    elParent = null

if(el) {
  elParent = el.parentNode
}
1, a level 4 CSS selector. We covered its needs, some cases where it can replace JavaScript in your frontend projects, and general to advanced use cases.

We also discussed the current support offered to it by different browsers, and learned how to check for the browser support.

Thanks for reading all the way through. I hope you learned something new through this. Feel free to share more examples of how

let el = document.querySelector(".someElement"),
    elParent = null

if(el) {
  elParent = el.parentNode
}
1 can be useful in the comments.

Is your frontend hogging your users' CPU?

As web frontends get increasingly complex, resource-greedy features demand more and more from the browser. If you’re interested in monitoring and tracking client-side CPU usage, memory usage, and more for all of your users in production, try LogRocket.
CSS if parent has class
CSS if parent has class
https://logrocket.com/signup/

LogRocket is like a DVR for web and mobile apps, recording everything that happens in your web app or site. Instead of guessing why problems happen, you can aggregate and report on key frontend performance metrics, replay user sessions along with application state, log network requests, and automatically surface all errors.

How to apply CSS to child if parent has class?

It's easy to apply style to a child element, but if you want to apply style to a parent class that already has child elements, you can use the CSS selector child combinator ( > ), which is placed between two CSS selectors. For example, div > p selects all <p> elements where the parent is a <div> element.

How to select child based on parent in CSS?

The element>element selector is used to select elements with a specific parent. Note: Elements that are not directly a child of the specified parent, are not selected.

How do you check if an element has a class CSS?

To check if an element contains a class, you use the contains() method of the classList property of the element:.
element.classList.contains(className);.
const div = document.querySelector('div'); div.classList.contains('secondary'); // true..

Does CSS have a parent selector?

Using :has() as a CSS Parent Selector and much more | WebKit.