How to select a parent of a css class?
I want to add styles to all the <div>
elements that contains a child element with a specific CSS class (child-class
in the example).
Is there a way to select parent elements with native CSS?
<div>
<span class="child-class"></span>
</div>
Solution
Yes, there is a new CSS :has
pseudo-class that allows selecting parent elements based on children classes
div:has(> .child-class-name) {
//add parent style here
}
This will allow you to add styling to the parent div without using any javascript
Have a look at :has documentation for browser compatibility info
Alternative #1
I've been using the :has()
selector for a while now, but one thing to keep in mind is browser support. While it's great in modern browsers, you might need fallbacks for older ones.
Here's a more robust approach I use:
/* Modern browsers */
.parent:has(.child-class) {
background-color: blue;
}
/* Fallback for older browsers */
@supports not (selector(:has(*))) {
.parent-with-child {
background-color: blue;
}
}
Or you can use CSS custom properties for better control:
.parent:has(.child-class) {
--parent-bg: blue;
--parent-border: 2px solid red;
}
.parent {
background-color: var(--parent-bg, transparent);
border: var(--parent-border, none);
}
This way, you can style the parent based on child conditions while maintaining backward compatibility.
Alternative #2
Another approach I've found useful is using CSS Grid or Flexbox to achieve similar effects without relying on :has()
. Sometimes you can restructure your HTML to make parent selection unnecessary.
Instead of:
<div class="parent">
<span class="child-class">Content</span>
</div>
You could use:
<div class="container">
<div class="parent" data-has-child="true">
<span class="child-class">Content</span>
</div>
</div>
Then style with:
.parent[data-has-child="true"] {
background-color: blue;
}
Or use CSS Grid to create the effect:
.container {
display: grid;
grid-template-columns: 1fr;
}
.parent {
background-color: transparent;
}
.parent:has(.child-class) {
background-color: blue;
}
This approach gives you more control and better browser support.
Alternative #3
If you're working with dynamic content or JavaScript frameworks, you might want to consider a hybrid approach that combines CSS with minimal JavaScript.
Here's a solution I've used in React/Vue projects:
// JavaScript to add a class to parents with specific children
document.querySelectorAll('.child-class').forEach(child => {
child.closest('.parent').classList.add('has-child-class');
});
Then style with regular CSS:
.parent.has-child-class {
background-color: blue;
border: 2px solid red;
}
Or if you're using a CSS-in-JS solution:
const ParentStyle = styled.div`
background-color: transparent;
${props => props.hasChild && `
background-color: blue;
border: 2px solid red;
`}
`;
This approach is more reliable across all browsers and gives you programmatic control over when the parent styling is applied.