has() selector

⚡ TL;DR

A new, very powerful, CSS selector, opening previously impossible selectors without either CSS pre-processor or JS:

  • parent selector (style ancestors based on their children)
  • previous sibling
  • cousins (style elements based on some other element with a common ancestor but not siblings)

🧪 Experiment

❌ Your browser does NOT support the feature tested below. Try another browser

#1 - Modify a parent selector

Example: theme toggle with no js

We'll modify global values (<body> colors) based on the state of an input low down the DOM tree (the <checkbox> `checked`)


<label for='dark-theme-toggle'>
  <span class='dark-theme'>Activate dark theme🌙</span>
  <input
    id='dark-theme-toggle'
    type='checkbox'
    aria-label='active-dark-theme'
  />
</label>

body:has(#dark-theme-toggle:checked) {
  --bg-primary: #000;
  --txt-primary: #fff;
}

#2 - Modify a consin

<common ancestor element>

<a div element>

<cousin element earlier in the DOM tree>

<another div element>

<cousin element later in the DOM tree>


<div class='common-ancestor'>common ancestor element

    <div>a div element

        <p class='early-cousin'>cousin element earlier in the DOM tree</p>

    </div>

    <div>another div element

        <p class='state-to-check'>cousin element later in the DOM tree</p>

    </div>
</div>

.common-ancestor:has(.state-to-check) .early-cousin {
    background-color: deeppink;
}

🤔 Opinion

📚 Resources

💻 Support

Data on support for the css-has feature across the major browsers from caniuse.com