Simplify CSS selector grouping and styling with :where() and :is()

CSS (Cascading Style Sheets) is a powerful tool used to add styling and formatting to web pages. One of the most recent additions to CSS is the :where() and :is() pseudo-classes. These classes offer new ways to select elements on a webpage, making it easier to apply styles to multiple elements at once.

In this blog, we’ll explore what :where() and :is() are and how they can be used in CSS.

Before the introduction of the :where() and :is() pseudo-classes, applying styles to multiple selectors required using a comma-separated list of selectors.

For example:

  h1, h2, h3, h4, h5, h6 {
    color: red;
  }

This would apply the color: red style to all heading elements from h1 to h6. If we wanted to exclude some selectors from the list, we would need to repeat the entire list and then remove the ones we don’t want.

For example, let’s say we wanted to apply the color: red style to all headings except for h4.

  h1, h2, h3, h5, h6 {
    color: red;
  }

This works, but as the list of selectors gets longer, it becomes more difficult to maintain and understand which selectors are included and excluded?

Another issue was that this approach didn’t allow for the nesting of selectors. For example, let’s say we have a div element that contains multiple heading elements and we want to apply the color: red style to only the heading elements inside that div:

  div h1, div h2, div h3, div h4, div h5, div h6 {
    color: red;
  }

Again, this CSS works, but as the list of selectors gets longer and more complex, it becomes harder to read and maintain.

The :where() and :is() pseudo-classes provide a cleaner and more flexible way to apply styles to multiple selectors. They allow for nesting and make it easier to exclude or include specific selectors without repeating the entire list.

Let’s deep dive into these selectors.

What is :where() in CSS?

The :where() pseudo-class was introduced in the Selectors Level 4 specification It is used to group a set of selectors. The :where() pseudo-class can be used to select elements based on multiple criteria, making it easier to apply styles to multiple elements at once.

Here’s an example of how :where() can be used:

  :where(h1, h2, h3) {
    color: blue;
  }

In this example, we’re selecting all the h1, h2, and h3 elements and applying a blue color to them.

This is equivalent to writing:

  h1, h2, h3 {
    color: blue;
  }

What is :is() in CSS?

The :is() pseudo-class was also introduced in the Selectors Level 4 specification. It is used to group a set of selectors, just like :where(). However, the difference is that :is() only selects elements that match at least one of the given selectors.

Here’s an example of how :is() can be used:

  :is(h4, h5, h6) {
    color: red;
  }

In this example, we’re selecting all the h1, h2, and h3 elements and applying a blue color to them. This is the same as the previous example using :where(). However, using :is() allows us to write our code more concisely and make it easier to read.

Invalid selectors

In the old way of applying styles to multiple selectors using a comma-separated list, if any of the selectors in the list was invalid, the entire rule would be ignored. For example, if we had the following rule:

  <a class="7a">Link</a>
  h1, h2, h3, h4, h5, h6, 7a {
    color: red;
  }

Notice here that the 7a is an invalid selector. In this case, the color: red style would not be applied to any of the headings.

Using :where, 7a selector is ignored and the rest of the styles are applied.

For example:

  :where(h1, h2, h3, h4, h5, h6, 7a) {
    color: red;
  }

Differences between :where() and :is()

Although :where() and :is() are similar, there are some differences between the two:

1. :where() groups a set of selectors, while :is() selects elements that match at least one of the given selectors.

Here’s an example to illustrate it:

    <ul>
      <li class="selected">Apple</li>
      <li class="selected">Banana</li>
      <li>Orange</li>
      <li class="selected">Grapes</li>
    </ul>
  

Now let’s say we want to select all the list items that are either have selected class or the first items. We can achieve this using :is() and :first-child selectors as follows:

    li:is(.selected, :first-child) {
      color: red;
    }
  

This will select the first item in the list (Apple) and the two selected items (Banana and Grapes), and make their text color red.

Now, let’s say we want to select all list items that come after the first item. We can use :where() with :not(:first-child) selector as follows:

    li:where(:not(:first-child)) {
      color: red;
    }
  

This will select all the list items that come after the first item except the first item (Apple).

2. :where() always has 0 specificity, whereas :is() takes on the specificity of the most specific selector in its arguments.

Let’s understand this by taking an example:

    <div class="container">
      <h1 class="title">Hello, world!</h1>
    </div>
  

Let’s say we want to apply a red color to both the h1 element and the .container element.

Using :where(), we can write:

    :where(h1, .container) {
      color: blue;
    }
  

:where() has 0 specificity which means it doesn’t contribute to specificity.

This rule will have lower specificity than a selector with a class or an element selector, which means that it can be overridden by more specific rules.

Here h1 selector overrides the :where selector.

    :where(h1, .container) {
      color: blue;
    }
    h1 {
      color: green;
    }
  

Now let’s see how :is() works.

    :is(h1, .container) {
      color: red;
    }
    h1 {
      color: blue;
    }
  

The specificity of the :is selector is the same as the selector with the highest specificity in the argument list. In our case, it is .container.

Therefore, the specificity of this rule is 0-1-1 (0 for :is(), 1 for the class selector, and 1 for the element selector).

:is selector overrides h1 selector styles.

Thumb rule:

In general, :where() is useful when you want to apply styles to a set of selectors without increasing specificity. Whereas :is() is useful when you want to apply styles to a set of selectors with a specific level of specificity.

CSS :where() and :is() Browser Support

Browser version that fully supports the :where() and :is().

Image Credits: CanIUse

Image Credits: CanIUse

Conclusion

The :where() and :is() pseudo-classes are powerful tools that make it easier to select and style elements on a webpage. With the introduction of these new pseudo-classes, CSS continues to evolve and become more powerful, making it an essential tool for web designers and developers.

Refer to :where() and :is() to have more idea about these Pseudo classes.

Need help on your Ruby on Rails or React project?

Join Our Newsletter