How Does the CSS :is() Pseudo-Class Work?

The CSS :is() pseudo-class reduces code repetition and simplifies complex selector patterns by grouping multiple selectors into a single, clean declaration. By accepting a forgiving selector list and adopting the specificity of its most specific argument, :is() helps developers write DRY (Don't Repeat Yourself) style sheets, target deeply nested elements effortlessly, and avoid selector-breaking syntax errors.

The Problem with Traditional CSS Selectors

When writing styles for nested or varied document structures, developers often encounter repetitive selector chains. For instance, styling headings across different container elements traditionally requires explicitly listing every combination:

header h1,
header h2,
header h3,
article h1,
article h2,
article h3,
footer h1,
footer h2,
footer h3 {
  color: #1a202c;
  margin-bottom: 0.5rem;
}

This pattern has several drawbacks:

How :is() Streamlines Groupings

The :is() pseudo-class condenses multi-branch selectors by taking a comma-separated list of targets and applying the rule to any matching branch.

The previous nine-selector block can be rewritten with a single line:

:is(header, article, footer) :is(h1, h2, h3) {
  color: #1a202c;
  margin-bottom: 0.5rem;
}

You can place :is() anywhere in a selector sequence—at the beginning, middle, or end. For example, applying hover and focus states across interactive elements becomes significantly more readable:

button:is(:hover, :focus-visible),
a.btn:is(:hover, :focus-visible) {
  background-color: #2b6cb0;
}

Specificity Rules of :is()

A critical mechanic of :is() is how it calculates specificity. Rather than having no specificity or taking an average, the specificity of :is() is determined by its most specific selector argument.

For example, consider the following selector:

:is(div, #unique-id, .regular-class) p {
  color: blue;
}

Even when this rule matches a paragraph inside a generic div, the :is(...) token carries the specificity weight of #unique-id (an ID selector). As a result, the entire selector evaluates to [1, 0, 1] (one ID, zero classes, one element).

Understanding this behavior ensures that styling rules do not unintentionally overpower other CSS declarations with higher cascade priority.

Forgiving Selector Parsing

In standard CSS selector lists, an invalid or unsupported selector breaks the entire rule block:

/* If the browser does not support :unsupported-pseudo, the whole block fails */
.valid-class,
:unsupported-pseudo {
  display: flex;
}

The :is() pseudo-class utilizes forgiving selector list parsing. If any selector inside :is() is unrecognized or invalid, the browser simply ignores the invalid item and continues styling the remaining valid selectors:

/* The rule still applies to .valid-class even if :unsupported-pseudo fails */
:is(.valid-class, :unsupported-pseudo) {
  display: flex;
}

This makes :is() resilient when working with experimental features, vendor prefixes, or evolving web standards.

Practical Use Cases