:is() and :where() in CSS: grouping selectors without repeating them

:is() and :where() group repetitive selectors together, but only :where() keeps a zero specificity, unlike :is().
4 min read
Believemy logo

Some stylesheets repeat the same selector prefix over and over, line after line. :is() and :where() solve that problem by grouping several selectors into one, while behaving very differently on one crucial point: specificity.

Understanding that difference avoids hours of debugging when a rule unexpectedly overrides a style that seemed protected.


Definition

:is() and :where() accept a comma separated list of selectors and treat it as a single alternative. The rule that uses them applies as soon as one selector in the list matches the element.


Grouping repetitive selectors

CSS
/* without :is(), three repeated selectors */
header h1,
main h1,
footer h1 {
  font-family: "Georgia", serif;
}

/* with :is(), a single grouped selector */
:is(header, main, footer) h1 {
  font-family: "Georgia", serif;
}

The visual result is strictly identical between the two versions, but the second one is shorter, easier to maintain, and removes the risk of forgetting to update one of the three selectors if the rule ever changes.


The specificity trap

This is where the two syntaxes diverge radically. The Specificity of :is() matches that of its strongest argument in the list: if the list contains an id, the whole rule inherits the weight of an id, even for the other selectors in the list that are simple classes. :where(), on the other hand, has a specificity of zero, no matter how complex the selectors it groups are. A rule written with :where() can therefore be overridden by any other rule, even the simplest one, which makes it a valuable tool for writing base styles that stay easy to override.

SyntaxSpecificityTypical use
:is(...)That of the strongest selector in the listGrouping without changing behavior
:where(...)Always zeroBase styles that stay easy to override


A concrete example of the trap

CSS
/* the specificity of :is() here equals that of #main */
:is(#main, .secondary) p {
  color: navy;
}

/* this simpler rule will NOT be able to win */
p {
  color: crimson;
}

Even when the targeted element actually matches .secondary and not #main, the whole rule still inherits the weight of the id present in the list. That behavior, often poorly anticipated, is what makes a rule written with :is() surprisingly hard to override.

Good to knowTo group selectors without ever inflating a rule's specificity, default to :where() over :is(), unless there is a specific reason to inherit the weight of the strongest selector.


When to prefer :not() over :is()

:is() and :not() answer different needs. :is() groups alternatives that should all trigger the same style, while :not() excludes one precise case from a broader group. They often get combined inside the same selector, for instance to target every heading except ones located inside a footer, while grouping several heading levels into a single rule.

CSS
:is(h2, h3, h4):not(footer *) {
  scroll-margin-top: 80px;
}

This rule adds scroll margin to every heading from level two through four, except the ones inside the footer, in a single line rather than several separate selectors.


Frequently asked questions

QuestionCan :is() and :where() be used with pseudo-classes like :hover?

Yes, the list can contain any valid type of selector, including pseudo-classes, which makes it possible for example to group several states inside a single rule.

QuestionDo :is() and :where() accept a nested CSS selector?

Yes, the list can contain compound selectors, such as combinations of classes or combinators, as long as each entry in the list remains a valid selector on its own.

QuestionWhat happens if one selector in the list is invalid?

With :is(), an invalid selector inside the list does not invalidate the others, the rule keeps working for the remaining valid selectors, unlike the behavior of a classic comma separated list in a plain selector.

Related terms

Discover our hTML and CSS glossary

Browse the terms and definitions most commonly used in HTML and CSS development.

Share this article

Want to help us? Share this article on your networks or even better: on your site, in an article or in your newsletter.