What Is the Difference Between CSS :is() and :where()?

Both the :is() and :where() pseudo-class functions allow developers to group multiple selectors into a single, compact rule and benefit from forgiving selector lists. While their syntax, browser support, and grouping mechanisms are identical, their single functional difference lies entirely in specificity: :where() always carries a specificity score of zero regardless of its contents, whereas :is() takes on the specificity of the most specific selector in its argument list.

Understanding Specificity in CSS

CSS specificity determines which style declaration takes precedence when multiple rules target the same element. It is commonly calculated as a three-part score:

When using standard nested or grouped selectors, every element in the chain adds to the overall specificity score.

How :is() Handles Specificity

The :is() pseudo-class dynamically adopts the specificity of the most specific selector provided inside its parentheses. Even if an element matches a simpler selector within the list, the entire rule is scored against the highest-weighted argument.

/* Specificity is determined by #main-nav (1, 0, 0), not .menu (0, 1, 0) or header (0, 0, 1) */
:is(header, .menu, #main-nav) a {
  color: blue;
}

In the example above, targeting header a will evaluate with an ID-level specificity of (1, 0, 1) because #main-nav is inside the selector list. This can make subsequent overrides harder to apply unless equally specific selectors are used.

How :where() Handles Specificity

The :where() pseudo-class strips all specificity from its arguments, always evaluating to (0, 0, 0). The only specificity applied to the overall rule comes from whatever selectors exist outside of :where().

/* Specificity is (0, 0, 1) solely from the 'a' tag */
:where(header, .menu, #main-nav) a {
  color: blue;
}

Even though #main-nav is listed inside :where(), the rule can be overridden by any single class, tag, or utility selector later in the stylesheet:

/* Overrides the rule above because a class has specificity (0, 1, 0) */
a.nav-link {
  color: red;
}

Side-by-Side Comparison

Feature :is() :where()
Specificity Calculation Specificity of the most specific argument Always zero (0, 0, 0)
Forgiving Selector List Yes (invalid selectors are ignored) Yes (invalid selectors are ignored)
Primary Use Case Reducing repetition without reducing specificity CSS resets, base component defaults, theme layers
Ease of Overriding Harder (depends on argument specificity) Very easy (any standard selector overrides it)

When to Use :is() vs. :where()

Use :where() when writing foundational CSS, such as CSS resets, third-party component libraries, or base typography sheets. Because :where() creates zero-specificity rules, end users and consumers can easily override styles with simple utility classes without relying on !important or overly complex selector chains.

Use :is() when grouping selectors to clean up complex stylesheets where the existing specificity structure must remain intact to prevent unintentional style leaks across different application states.