The Publishing Project

:is() CSS pseudo-class

There are times when we want the same element across the page to do the same.

The following block styles the h2 elements inside the header, footer and main elements.

header h2,
main h2,
footer h2 {
  color: red;
}

It works but it’s error-prone, repetitive and may cause all rules to be ignored if there is a mistake.

Published in Selectors Level 4, the :is() pseudo-classtakes a selector list and selects any element that matches any of the selectors in that list. Using :is() e can write the previous example like this

:is(header, main, footer) h2 {
  color: red;
}

Older browsers support this functionality as :matches(), or through an older, prefixed pseudo-class — :any(), including older versions of Chrome, Firefox, and Safari. :any() works in exactly the same way as :matches()/:is(), except that it requires vendor prefixes and doesn’t support complex selectors.

The specificity of the :is() pseudo-class is the highest specificity of the :is() arguments plus the specificity of the remaining arguments in the selector

For example the specificity for all h2 elements that match the following CSS rule:

:is(#header main footer) h2 {
  font-weight: 700;
}

is 1-0-1. They all take the highest specificity of the attributes for the :is() pseudo class plus any remaining attributes for the selector. The highest specificity for the :is attributes is the one for #header (shown as 1-0-0) and the specificity for h2 is 0-0-1). This behavior is different than older selectors like :any() or :matches() where the specificity was calculated differently

For a basic primer on specificity see Estelle Weyl’s CSS Specificity and the CSS Specifishity Chart

Because :is is not implemented in all browsers, some browsers require vendor prefixes and some browsers use earlier versions of the pseudo-class like :matches.

/* basic syntax without pseudo classes */
header h2,
main h2,
footer h2 {
  font-weight: 700;
  color: rebeccapurple;
}

/* older webkit */
:-webkit-any(header, main, footer) h2 {
  font-weight: 700;
  color: rebeccapurple;
}

/* older Firefox syntax */
:-moz-any(header, main, footer) h2 {
  font-weight: 700;
  color: rebeccapurple;
}

/* Older syntax using :matches() */
:matches(header, main, footer) h2 {
  font-weight: 700;
  color: rebeccapurple;
}

:is() and :where() accept a forgiving selector list.

In CSS when using a selector list, if any of the selectors are invalid then the whole list is deemed invalid. When using :is() or :where() instead of the whole list of selectors being deemed invalid if one fails to parse, the incorrect or unsupported selector will be ignored and the others used.

:is(#header, :unsupported) h2{
  font-weight: 700;
  color: rebeccapurple;
}

Will still parse correctly and match supported values, even in browsers which don’t support :unsupported, whereas:

#header h2, 
:unsupported h2 {
  font-weight: 700;
  color: rebeccapurple;
}

Will be completely ignored in browsers that don’t support :unsupported even if they support the other selectors.