I’ve seen a handful of recent posts talking about the utility of the :is()
relational pseudo-selector. No need to delve into the details other than to say it can help make compound selectors a lot more readable.
:is(section, article, aside, nav) :is(h1, h2, h3, h4, h5, h6) {
color: #BADA55;
}
/* ... which would be the equivalent of: */
section h1, section h2, section h3, section h4, section h5, section h6,
article h1, article h2, article h3, article h4, article h5, article h6,
aside h1, aside h2, aside h3, aside h4, aside h5, aside h6,
nav h1, nav h2, nav h3, nav h4, nav h5, nav h6 {
color: #BADA55;
}
There’s just one catch: the specificity. The selector’s specificity matches the most specific selector in the function’s arguments. That’s not a big deal when working with a relatively flat style structure containing mostly element and class selectors, but if you toss an ID in there, then that’s the specificity you’re stuck with.
/* Specificity: 0 0 1 */
:is(h1, h2, h3, h4, h5, h6) {
color: #BADA55;
}
/* Specificity: 1 0 0 */
:is(h1, h2, h3, h4, h5, h6, #id) {
color: #BADA55;
}
That can be a neat thing! For example, you might want to intentionally toss a made-up ID in there to force a style the same way you might do with the !important
keyword.
What if you don’t want that? Some articles suggest nesting selectors instead which is cool but not quite with the same nice writing ergonomics.
There’s where I want to point to the :where()
selector instead! It’s the exact same thing as :is()
but without the specificity baggage. It always carries a specificity score of zero. You might even think of it as a sort of specificity reset.
/* Specificity: 0 0 0 */
:where(h1, h2, h3, h4, h5, h6) {
color: #BADA55;
}
/* Specificity: 0 0 0 */
:where(h1, h2, h3, h4, h5, h6, #id) {
color: #BADA55;
}
So, is there a certain selector hijacking your :is()
specificity? You might want :where()
instead.