Using Modern CSS :is() to Reduce Selector Repetition
The modern CSS :is() pseudo-class significantly reduces
repetition in web stylesheets by allowing developers to group multiple
selectors into a single, compact rule. Instead of repeatedly writing out
long descendant paths and combinators for different elements or
contexts, :is() acts as a grouping function that applies a
single declaration block across all specified targets. This article
explores how :is() works, compares it to legacy approaches,
and explains how it cleans up complex style rules while improving
stylesheet maintainability.
The Problem of Repetitive Selectors
Historically, applying the same set of styles to elements across different containers required repeating the entire selector chain for each variation. For example, styling headings inside multiple structural wrappers commonly resulted in verbose, bloated rules:
header h1,
header h2,
header h3,
nav h1,
nav h2,
nav h3,
footer h1,
footer h2,
footer h3 {
color: #333;
line-height: 1.2;
}This traditional syntax introduces several issues: it inflates stylesheet file size, makes rules harder to read, and increases the risk of human error when updating or maintaining selectors.
How :is() Eliminates
Duplication
The :is() pseudo-class accepts a comma-separated list of
selectors as its argument and matches any element that can be selected
by one of the items in that list.
Using :is(), the previous nine-line selector collapses
into a single, straightforward declaration:
:is(header, nav, footer) :is(h1, h2, h3) {
color: #333;
line-height: 1.2;
}The browser evaluates the expression by pairing each container
(header, nav, footer) with each
nested element (h1, h2, h3),
removing the need to manually declare all nine combinations.
Simplifying State and Context Combinations
The reduction in repetition becomes even more pronounced when dealing with interactive states, such as links inside specific components:
/* Traditional method */
.card a:hover,
.card a:focus,
.card a:active {
text-decoration: underline;
}
/* Modern method with :is() */
.card a:is(:hover, :focus, :active) {
text-decoration: underline;
}This approach keeps the primary selector context
(.card a) clear and isolates only the variations that
change.
Specificity and Fault Tolerance
Beyond conciseness, :is() offers two key behaviors that
benefit complex styling:
Calculated Specificity: The specificity of an
:is()selector is not zero; instead, it adopts the specificity of the most specific selector in its argument list. For example, in:is(#main, .content) p, the rule carries the specificity weight of an ID (#main), regardless of whether the matched element sits within#mainor.content.Forgiving Parsing: Standard CSS selector lists are invalid if a single selector in the list is unsupported or malformed, causing the entire block to fail. In contrast,
:is()uses a forgiving selector list. If one argument inside:is()is invalid or unsupported by the browser, the browser ignores the broken item and still applies the styles to the valid ones.
By combining concise syntax, adaptable specificity, and robust
parsing, the :is() pseudo-class transforms complex selector
architecture into clean, scalable CSS.