
Three important things you should know about CSS :is()
Three important things you should know about CSS :is() êŽë š

Back in 2019 I shared how the CSS :is() selector will simplify things when writing CSS. What I didnât know back then, and only have learnt quite recently, are these three important facts about CSS :is():
Letâs take look at what that means.
1. The selector list of :is() is forgiving
What if you include a selector thatâs pure gibberish inside :is()? Will the rule-set be declared invalid or what?
p:is(.foo, #bar, $css:rocks) {
color: hotpink;
}
Thankfully :is() is very forgiving here: the $css:rocks part â which in itself is an invalid CSS selector â will simply be ignored, while keeping the rest of the selector list in place.. So using the snippet above, both p.foo and p#bar will be colored hotpink. Yay!
Should you try this without :is(), the whole rule-set would become invalid. In the snippet below, none of the paragraphs will be hotpink due to that faulty $css:rocks selector invalidating the whole selector list.
p {
font-family: sans-serif;
}
p.foo, p#bar, p$css:rocks { /* â This whole rule-set is declared invalid */
color: hotpink;
}
Note that the paragraphs will have font-family: sans-serif applied, as itâs only the invalid rule-set that ends up being ignored.
đź
In the near future this latter behavior will no longer be the case as the CSSWG intends to modify these rules such that an invalid selector will simply be ignored rather than invalidating the whole selector list. Relevant CSS WG Issue: 3264 (w3c/csswg-drafts)
2. The specificity of :is() is that of its most specific argument
Take the code below. What color will p.foo have?
p:is(.foo, #bar, $this:invalid) {
color: hotpink;
}
p.foo {
color: lime;
}
I wonât be lime but hotpink! This because when calculating the specificity, the specificity of the :is() pseudo-class is replaced by the specificity of its most specific argument.
p.foohas a specificity of(0,1,1)p:is(.foo, #bar)has a specificity of(1,0,1)
As p:is(.foo, #bar) has a higher specificity, it will âwinâ here.
âïž
The :not() and :has() pseudo-classes also have their specificity calculated this way.
âïž
If you donât want to be affected by this, you can use :where() instead of :is(). It works in the same way :is() does, but will always have a specificity of 0. You can cleverly wrap this around other selectors to undo their specificity. Think of :where(:not(âŠ)) for example.
đŹ
Although I wouldnât recommend it, you could perfectly do something like :is(#bump#up#the#spe#ci#fi#city#yo, .foo) to override selectors more specific than .foo âŠ
3. :is() does not work with pseudo-element selectors (for now)
If you read up on the definition of :is() youâll read that it accepts a âSelector Listâ which is a comma-separated list of simple, compound, or complex selectors.
When looking up simple selectors, thereâs an interesting thing to note:
A type selector, universal selector, attribute selector, class selector, ID selector, or pseudo-class is a simple selector.
Do you see it? Here: pseudo-element selectors are not included in this list. As a result, :is() does not play nice with pseudo-element selectors such as ::before, ::after, âŠ.
đź
In the future this will become possible though, but not just yet. Relevant CSSWG Issue: 2284 (w3c/csswg-drafts)
Knowing these three facts about :is() will surely help you understand it better and make using it more fun!
If you understood well, the Pen above should hold no secrets to you anymore đ