Preface
The CSS :has() selector is a game-changer, allowing you to style parent elements based on their children. This capability opens up a world of possibilities for creating dynamic and responsive designs. Whether you’re aiming to highlight specific sections, adjust layouts based on content, or create more interactive user experiences, the :has() selector is a powerful tool to have in your arsenal. Let’s dive in and explore how you can leverage this selector to enhance your web projects.
What is the CSS :has() Selector?
The CSS :has() selector, also known as the relational pseudo-class, selects an element if it contains at least one element that matches the specified selector. In simpler terms, it lets you target a parent element based on whether it has a specific child element or not. This is a significant departure from traditional CSS selectors, which primarily focus on styling elements based on their own properties or their ancestors.
For example, you can use :has() to style a <div> element differently if it contains an <img> tag or a specific class. This level of contextual styling was previously difficult to achieve with CSS alone, often requiring JavaScript.
Definition: The CSS `:has()` selector allows you to style a parent element based on the presence or characteristics of its children.
Basic Syntax
The basic syntax of the :has() selector is straightforward:
parent-element:has(child-selector) {
/* Styles to apply to the parent-element */
}
Here, parent-element is the element you want to style, and child-selector is the selector that the parent must contain for the styles to be applied.
Use Cases and Examples
Styling List Items with Images
One common use case is styling list items that contain images. For instance, you might want to add a border to list items that have an image to make them stand out.
- Item 1
Item 2- Item 3
li:has(img) {
border: 2px solid #007bff; /* Blue border */
padding: 10px;
}
In this example, only the list item containing the image will have a blue border and padding.
Highlighting Sections with Specific Content
Another use case is highlighting sections of a page that contain certain types of content, such as a call-to-action button.
Section Title
Some text in the section.
Call to Action
section:has(.cta-button) {
background-color: #f0f8ff; /* Light blue background */
padding: 20px;
}
This will apply a light blue background and padding to any <section> that contains an element with the class cta-button.
Responsive Design Adjustments
The :has() selector can also be used to make responsive design adjustments based on the content within a container. For example, you might want to change the layout of a container if it contains more than a certain number of items.
.container:has(> *:nth-child(5)) {
display: flex;
flex-direction: row;
}
This CSS will change the display property of .container to flex and set the flex-direction to row if it contains more than 5 child elements. This can be useful for creating dynamic layouts that adapt to different amounts of content.
Advanced Techniques
Using :has() with Multiple Selectors
The :has() selector can also accept multiple selectors, allowing for more complex conditions. For example, you can style a parent element only if it contains both an image and a specific class.
.parent:has(img.featured, .special-text) {
border: 3px solid green;
}
This will apply a green border to the .parent element only if it contains both an <img> tag with the class featured and an element with the class .special-text.
Combining :has() with Other Pseudo-Classes
You can combine :has() with other pseudo-classes like :hover to create interactive effects. For example, you can change the background color of a parent element when the user hovers over a specific child element.
.parent:has(.child:hover) {
background-color: #ffffe0; /* Light yellow background */
}
In this case, the .parent element will change its background color to light yellow when the user hovers over the .child element.
Using :has() with the :not() Pseudo-Class
The :not() pseudo-class can be combined with :has() to style elements that do not contain a specific child. This can be useful for applying default styles and then overriding them when a certain condition is met.
.parent:not(:has(.no-content)) {
padding: 15px;
}
Here, the .parent element will have padding unless it contains an element with the class .no-content.
Browser Compatibility
While the :has() selector is incredibly powerful, it’s essential to be aware of its browser compatibility. As of late 2023, :has() is supported in most modern browsers, including Chrome, Firefox, Safari, and Edge. However, older versions of these browsers may not support it. Always check the MDN Web Docs for the most up-to-date information on browser support.
Info: Always check the current browser compatibility before implementing `:has()` in production environments.
Alternatives and Fallbacks
If you need to support older browsers that don’t support :has(), you might consider using JavaScript as a fallback. JavaScript can detect the presence of specific child elements and apply styles accordingly.
Here’s an example using JavaScript:
const parents = document.querySelectorAll('.parent');
parents.forEach(parent => {
if (parent.querySelector('.child')) {
parent.classList.add('has-child');
}
});
.parent.has-child {
border: 1px solid red;
}
This JavaScript code selects all elements with the class .parent, checks if they contain an element with the class .child, and adds a class has-child to the parent if the condition is met. You can then use CSS to style the .parent.has-child elements.
Hint: Consider using progressive enhancement by implementing `:has()` and using JavaScript as a fallback for older browsers.
Best Practices
- Keep Selectors Simple: Complex selectors can impact performance. Try to keep your
:has()selectors as simple as possible. - Test Thoroughly: Always test your designs in multiple browsers to ensure compatibility.
- Use Fallbacks: Provide fallback solutions for older browsers that don’t support
:has(). - Consider Accessibility: Ensure that your use of
:has()doesn’t negatively impact the accessibility of your website. For more insights on web accessibility, refer to resources like the Web Accessibility Initiative (WAI).
Integrating with WordPress and Elementor
For those building websites with WordPress, the :has() selector can be a powerful tool. You can add custom CSS to your WordPress theme to take advantage of this selector. If you’re using a page builder like Elementor (/go/elementor-pro), you can add custom CSS directly to specific sections or elements.
To add custom CSS in WordPress:
- Go to Appearance > Customize in your WordPress dashboard.
- Select Additional CSS.
- Add your CSS code, including the
:has()selector. - Click Publish to save your changes.
If you are using Elementor (/go/elementor-pro) you can add the :has() to each element as well
This allows you to create more dynamic and context-aware designs without needing to modify your theme files directly.
Info: When using `:has()` with WordPress, ensure your theme and plugins are compatible and up-to-date to avoid conflicts.
Real-World Examples and Inspirations
To get a better sense of what’s possible with the :has() selector, let’s look at some real-world examples:
- Dynamic Forms: You can style form containers based on whether they contain filled or empty input fields, providing visual feedback to the user.
- Conditional Content Display: You can adjust the layout of a page based on the presence of specific content elements, such as images or videos.
- Interactive Navigation: You can highlight navigation items based on the content being viewed, providing a clear visual indication of the user’s current location.
For inspiration, check out websites like CSS-Tricks and Smashing Magazine, which often showcase innovative uses of CSS selectors and techniques.
Conclusion
The CSS :has() selector is a powerful and versatile tool that can significantly enhance your ability to create dynamic and responsive web designs. By allowing you to style parent elements based on their children, it opens up new possibilities for contextual styling and interactive user experiences. While it’s essential to be aware of browser compatibility and provide fallbacks for older browsers, the benefits of using :has() are undeniable. Embrace this selector and take your web design skills to the next level. Start experimenting with :has() today and discover how it can transform your web projects. Don’t forget to regularly check resources like MDN Web Docs for updates on browser compatibility and best practices.



