:is() and :where()
Collapse repetitive selector lists into one and learn why :where() has zero specificity.
Ever written something like header h1, header h2, header h3 { ... } and felt your soul leave your body? :is() and :where() are the cure. Both take a list of selectors and match if any of them match.
/* Before */
header h1, header h2, header h3 { margin: 0; }
/* After */
header :is(h1, h2, h3) { margin: 0; }The one difference that matters
They look identical, but their specificity behaves in opposite ways:
:is()takes the specificity of its most specific argument. So:is(#id, p)is as heavy as an ID.:where()always has zero specificity, no matter what you put inside it.
That zero-specificity property makes :where() the perfect tool for authoring defaults and resets that anyone can override with a plain class — no specificity arms race, no !important.
Example
When to use it
- A developer collapses six repeated heading selectors into one :is(h1, h2, h3, h4, h5, h6) rule to apply shared font settings.
- A developer uses :where(.card, .panel, .modal) to apply shared base styles with zero specificity so component overrides remain easy.
- A designer uses :is(.dark-theme, .high-contrast) :is(h1, h2) to apply heading colors for two theme variations in one concise rule.
More examples
:is() collapses heading selector list
Uses :is() to apply shared heading styles without repeating a six-element selector list.
/* Without :is() β repeated 6 times */
/* h1, h2, h3, h4, h5, h6 { font-family: ...; } */
:is(h1, h2, h3, h4, h5, h6) {
font-family: Georgia, serif;
color: #1a1a2e;
line-height: 1.2;
}:where() for zero-specificity base
Applies shared base styles using :where() so its zero specificity never blocks component-level overrides.
/* :where() adds 0 specificity β any class overrides it easily */
:where(.card, .panel, .widget) {
background: #fff;
border: 1px solid #eee;
border-radius: 8px;
padding: 20px;
}
/* This override wins even though it's less verbose */
.card { border-color: #2965f1; }:is() for nested theme selectors
Combines :is() at two levels to apply dark-theme heading and body colors for two different theme attribute conventions.
:is(.dark-theme, [data-theme='dark']) :is(h1, h2, h3) {
color: #e0e0ff;
}
:is(.dark-theme, [data-theme='dark']) p {
color: #ccc;
}
Discussion