Understanding the CSS :where() Function

Image by Ondrej Supitar.

The CSS where() function is a relatively new feature that has been introduced to provide a more conditional way of grouping selectors, offering a way to specify multiple selectors without specificity impact. Whilst it's a very powerful tool, it's fair to say that its use in some of the projects I've worked on has sparked heated debate about its readability and usability compared to more conventional nesting.


What Is the :where() Function?

In essence, the where() function allows us to group selector alternatives whilst contributing zero specificity for the function and its arguments. A commaseparated selector list such as div, p, h1 { ... } does not accumulate specificity: each complex selector is calculated independently. By contrast, :is() takes the specificity of its most specific argument. As I've talked about before, specificity in CSS is probably one of the most misunderstood aspects of the language. :where() contributes zero specificity for itself and its arguments. This makes the grouped part easier to override and can help avoid specificity wars in complex stylesheets.

Here's a brief example of how :where() can be used to simplify grouped selectors whilst keeping specificity in check.

Without :where()

.header h1,.header h2,.header p {  margin-bottom: 1rem;}

With :where()

.header :where(h1, h2, p) {  margin-bottom: 1rem;}

In both of these examples, the styles apply to the h1, h2, and p elements inside .header. However:

  • Each selector in .header h1, .header h2, .header p is calculated separately; each has specificity (0,1,1).
  • .header :is(h1, h2, p) also has (0,1,1), because :is() adopts the most specific argument.
  • .header :where(h1, h2, p) has (0,1,0), because :where() and its arguments contribute zero.

This grouping of selectors inside of :where() can look appealing at first glance, but it also comes with its own problems, making it a little more difficult to read and understand during that same first glance.


Criticisms and Complexity

Despite its benefits, some developers (and especially the ones I've worked with recently) argue that :where() complicates code readability:

  • Abstract Selectors:

    It can obscure which elements the rule targets, especially in larger codebases.
  • Reduced Clarity:

    Conventional nesting conveys structural relationships clearly, whilst where() only groups selectors, which might not align with intuitive DOM hierarchies.

This second point can be particularly problematic when coming from a BEM background, where naming and. nesting logically follows the structure of the component.

For example, both of these add a 1em margin to the bottom edge of text inputs and buttons within a form:

/* Conventional selectors */form input[type='text'],form button {  margin: 1rem;}/* Using where() */form :where(input[type='text'], button) {  margin: 1rem;}

At a glance, it isn't immediately clear how the where() selectors relate to each other in the DOM, and when they appear midselector like above, they can become lost within the code.


Wrapping Up

The where() function in CSS introduces a powerful way to manage specificity and write modular styles, alongside a novel way to write grouped, nested selectors.

Whilst it's clearly very useful for situations that require zero specificity, its use in abstracting selectors can make code harder to follow compared to conventional nesting. As with any tool, its effectiveness depends on the context and how it is being used within your project.

Key Takeaways

  • The where() function enables conditional grouping of selectors with zero specificity.
  • It's great for fallback styles and utility classes but may reduce code readability.
  • Conventional nesting conveys structural relationships more intuitively.
  • Use where() thoughtfully to balance flexibility with maintainability.

Fin.


Untangling a delivery problem?

Send the symptoms, constraints, and affected routes. I'll help identify whether the issue sits in the application, platform, content model, deployment path, or search surface.