← All writing
Craft · · 2 min

:is() and :where()

They shorten the same selector lists. Only one of them keeps its weight, and that is the entire choice.

CSS Small Print

These get introduced together and the examples never distinguish them, so here is the only difference that matters.

selectors.css
/* both of these do the same matching */
:is(h1, h2, h3) a { }
:where(h1, h2, h3) a { }
CSS

:is() takes the specificity of its heaviest argument. :where() always has a specificity of zero.

So :is(h1, #masthead) a weighs as much as an id selector, even when it matched the h1. That surprises people exactly once, usually while they are wondering why a perfectly ordinary two-class rule underneath it is losing.

:where() weighing nothing is the useful one, and the place I now reach for it every time is a defaults layer. Anything I write in a reset or a base stylesheet goes in :where(). So it applies but never fights. A single class anywhere later beats it without a !important and without anybody thinking about it.

selectors.css
:where(ul, ol) {
  margin-block: 0;
  padding-inline-start: 0;
}
CSS

The other thing both give you is forgiving parsing. In a plain selector list, one selector the browser does not understand invalidates the whole rule. Inside either of these, the unknown one is skipped and the rest still work, which is why they turn up in cross-browser workarounds.

My rule, such as it is: :where() for anything meant to be overridden, :is() for anything meant to hold.

Read similar posts
2 min

light-dark()

Two color values in one declaration, picked by the color scheme, which removes most of the reason a theme needed a second block of custom properties at all.

2 min

scrollbar-gutter

The layout shifts by fifteen pixels when a modal opens, everybody blames the modal, and the actual cause is the scrollbar disappearing along with it.