CSS has()

Playing around with the CSS has() pseudo-class to see what it does.

a bored fish

Introduction

The relatively new :has() pseudo selector is pretty neat. I think it came into CSS core last year but I didn’t study it until now. It is worth having a play with to see what it can do.

In this example I created 2 traditional divs with a class of ‘card’ and 2 article tags. You will see that there is nothing special in the HTML, only that the content is lightly different in each.

<section>
  <div class="card">
    <h2>Example 1</h2>
    <h3>h3 Sub heading</h3>
    <p>A paragraph tag (p)</p>
  </div>
  <div class="card">
    <h2>Example 2</h2>
    <h4>h4 Sub heading</h4>
    <p>A paragraph tag (p)</p>
  </div>
  <article>
    <h2>Example 3</h2>
    <h3>h3 Sub heading</h3>
    <ul>
      <li>Unordered list (ul)</li>
    </ul>
  </article>
  <article>
    <h2>Example 4</h2>
    <p>A paragraph tag (p)</p>
  </article>
</section>

CSS has() - right to left, true or false

The basic syntax for :has() is as follows:

element:has(child) {
 /* style the element */
}

or, when working with element siblings a + is added. It is imperative that a space is used after the +!!

element:has(+ sibling-below) {
 /* style the element */
}

The way I see it working is the code to the right of the colon (:) returns either true or false. If false nothing happens. If true, the element to the left of the colon is styled as stated within the curly braces .

In other words, reading from the right if it exists style the element. If not do nothing.

CSS :has(), sibling example 1

The first example seeks h2 tags that have h3 siblings. All h2 with h3 siblings will be colored red. See cards 1 and 3 below.

h2:has(+ h3) {
 color: red;
}

CSS :has() sibling example 2

The second example seeks h2 tags that have p tag siblings. All h2 tags with p siblings will be colored teal. See card 4 below.

h2:has(+ p) {
 color: teal;
}

Card 1

h3 Sub heading

A paragraph tag (p)

Card 2

h4 Sub heading

A paragraph tag (p)

Card 3

h3 Sub heading

  • Unordered list (ul)

Card 4

A paragraph tag (p)

CSS :has() sibling example 3

The third example seeks any h3 tag that has unordered list ul tag siblings. All h3 tags with ul siblings will be colored purple. See card 3 above.

h3:has(+ ul) {
 color: rebeccapurple;
}

CSS :has() sibling example 4

The fourth example seeks any h4 tag that has p tag siblings. All h4 tags with p siblings will be colored blue. See card 2 above.

h4:has(+ p) {
 color: blue;
}

CSS :has() siblings example 5

The fifth example uses is() to hold multiple elements. In the case, any h2 or h3 tag with either p or ul siblings will be underlined. See card 1, 3 and 4 above.

:is(h2, h3):has(+ p, + ul) {
 text-decoration: underline;
}

CSS :has() child example 1

The example seeks any h3 tag that is a child of an article tag. Any article with an h3 heading will have a pink backgound. See card 3 above.

article:has(h3) {
 background-color: pink;
}

CSS :has() child example 2

The example seeks any h4 tag that is a child of an .card class. Any elament with a class of .card with an h4 child will have a yellow backgound. See card 2 above.

.card:has(h4) {
 background-color: yellow;
}

That’s it. Working with the has() pseudo selector is pretty straightforward if you understand the syntax. Further reading can be found within MDN docs.

Thank you for stumbling across this website and for reading my blog post entitled CSS has()