is() and where() Selectors
- CSS Basics
- Selectors & Specificity
- Box Model & Units
- Typography & Text Styling
- Colors & Color Spaces
- Positioning & Stacking Context
- Flexbox
- Grid
- Grid Advanced
- Responsive Design
- Container Queries
- Pseudo-classes & Pseudo-elements
- Modern Selectors
- CSS Custom Properties
- CSS Functions
- Transitions & Animations
- Transforms
- Forms & Input Styling
- CSS Architecture & Methodologies
- Accessibility in CSS
- Performance & Optimization
- View Transitions & Modern APIs
- Cascade Layers & Scope
The Repetition Problem They Solve
Without these selectors, matching several possible parent elements for the same child selector meant writing the whole chain out repeatedly.
/* Before: repetitive */
header p, main p, footer p {
margin-bottom: 1rem;
}Using :is() to Shorten the List
/* After: with :is() */
:is(header, main, footer) p {
margin-bottom: 1rem;
}:is() accepts a comma-separated list of selectors and matches an element if it matches any of them, letting a long repetitive selector collapse into one compact rule.
The Difference with :where()
:where() behaves identically to :is() in terms of what it matches, with one important difference: :where() always contributes zero specificity, no matter what selectors are inside it.
:where(header, main, footer) p {
margin-bottom: 1rem; /* very low specificity, easy to override later */
}Why the Specificity Difference Matters
:is() takes on the specificity of its most specific argument, which can make a rule surprisingly hard to override later. :where() is the safer default for base/reset styles that are meant to be easily overridden by more specific component styles further down the cascade.
Choosing Between Them
| Situation | Use |
|---|---|
| Writing a design system's low-level base styles | :where() - stays easy to override |
| Writing a specific, intentional override | :is() - specificity working in your favor |