DEV Community

Cover image for Exploring the :has() Selector in CSS
CodePassion
CodePassion

Posted on

Exploring the :has() Selector in CSS

CSS has progressed greatly over time, introducing a number of advanced selectors that improve the ability to style web pages with precision and flexibility. One of the most recent additions to the CSS selector is the :has() pseudo-class. This blog will go over the details of the :has() selector, including its usage, benefits, and practical examples to help you use this powerful tool in your web development projects.

What is the :has() Selector?
The :has() selector is a relational pseudo-class that lets you choose an element depending on the presence of a descendant or a more complicated relationship within its subtree. In simpler terms, it allows you to style a parent element if it contains specific child components.

Syntax:
The basic syntax of the :has() selector is as follows:

element:has(selector) {
  /* CSS properties */
}
Enter fullscreen mode Exit fullscreen mode

Practical Examples of :has() Selector :

Theme Chooser using :has Selector
Output:

Theme Chooser using :has Selector

HTML:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Theme Chooser</title>
</head>
<body>
    <header>
        <h1>Welcome to the Theme Chooser</h1>
        <div class="theme-selector">
            <label for="theme-select">Choose Theme:</label>
            <select id="theme-select">
                <option value="light">Light Mode</option>
                <option value="dark">Dark Mode</option>
                <option value="colorful">Colorful Mode</option>
            </select>
        </div>
    </header>
    <main>
        <p>This is an example of a theme chooser using the :has selector and a select tag.</p>
    </main>
</body>
</html>

Enter fullscreen mode Exit fullscreen mode

CSS:

body {
    font-family: Arial, sans-serif;
    background-color: #fff;
    color: #000;
    transition: background-color 0.3s, color 0.3s;
}

/* Header styling */
header {
    display: flex;
    justify-content: space-between;
    align-items: center;
    padding: 20px;
    background-color: #f0f0f0;
    border-bottom: 1px solid #ddd;
}

/* Align the theme selector to the right */
.theme-selector {
    display: flex;
    align-items: center;
    margin-left: auto;
}

/* Space between label and select */
.theme-selector label {
    margin-right: 10px;
}

/* Light Mode (Default) */
body {
    --bg-color: #fff;
    --text-color: #000;
    --header-bg-color: #f0f0f0;
    --header-border-color: #ddd;
}

/* Dark Mode styles using the :has selector */
:has(#theme-select option:checked[value="dark"]) body {
    --bg-color: #333;
    --text-color: #fff;
    --header-bg-color: #444;
    --header-border-color: #555;
}

/* Colorful Mode styles using the :has selector */
:has(#theme-select option:checked[value="colorful"]) body {
    --bg-color: #ffefd5;
    --text-color: #333;
    --header-bg-color: #ffdab9;
    --header-border-color: #eea2ad;
}

/* Applying CSS variables */
body {
    background-color: var(--bg-color);
    color: var(--text-color);
}

header {
    background-color: var(--header-bg-color);
    border-bottom: 1px solid var(--header-border-color);
}

/* Style for the main content */
main {
    padding: 20px;
}

/* Select tag styling */
select {
    padding: 5px;
    font-size: 16px;
    border: 1px solid #ccc;
    border-radius: 4px;
}

Enter fullscreen mode Exit fullscreen mode

Using variables in CSS, especially custom properties (variables), has various benefits that make stylesheets easier to manage, maintain, and extend. Here is why variables are used in the provided CSS.

Variables allow you to define a value once and reuse it throughout your stylesheet.

For instance:

body {
    --bg-color: #fff;
    --text-color: #000;
    --header-bg-color: #f0f0f0;
    --header-border-color: #ddd;
}

Enter fullscreen mode Exit fullscreen mode

These variables can then be utilised wherever needed, ensuring consistency and saving you from repeating the same value several times.

body {
    background-color: var(--bg-color);
    color: var(--text-color);
}

header {
    background-color: var(--header-bg-color);
    border-bottom: 1px solid var(--header-border-color);
}

Enter fullscreen mode Exit fullscreen mode

If you have to change a colour scheme or any other reusable property, you simply need to edit the variable value once, rather than hunting down each instance of the value in your CSS:

:has(#theme-select option:checked[value="dark"]) body {
    --bg-color: #333;
    --text-color: #fff;
    --header-bg-color: #444;
    --header-border-color: #555;
}

Enter fullscreen mode Exit fullscreen mode

The :has pseudo-class is a powerful CSS selector that enables you to style an element based on the presence of a descendant element that meets a specific condition. Within this context:

:has(#theme-select option:checked[value="dark"])

Enter fullscreen mode Exit fullscreen mode

This means the styles will be applied to the body element if there is an option element with the value “dark” that is checked within the #theme-select element.

option:checked[value=”dark”] targets an option element within the select that:

  1. Is checked (selected).
  2. Has a value attribute of “dark”.

The CSS rule you provided uses the :has pseudo-class in combination with CSS variables to implement a dynamic theming system. Read More examples of :has selector

Conclusion
The :has() selector is an extremely useful element in current CSS, allowing developers to construct more dynamic and context-aware styles. Understanding and utilising this selection allows you to improve the interactivity and visual attractiveness of your online projects while keeping the code clear and maintainable.

Top comments (0)