Here’s a rewritten version of the article with a clearer and more concise tone:

There’s been a lot of buzz lately about the usefulness of the CSS :is() pseudo-class. In short, it’s a powerful tool that makes complex selectors much easier to write and read.

:is(section, article, aside, nav) :is(h1, h2, h3, h4, h5, h6) {
  color: #BADA55;
}

/* Equivalent to writing out: */
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;
}

However, there’s a caveat: specificity. The :is() selector inherits the highest specificity of any selector inside it. That’s usually fine when you’re only working with element or class selectors, but if you include an ID, the entire rule takes on that higher specificity.

/* 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;
}

This behavior can actually be useful. For instance, you might intentionally include a fake ID to bump up specificity—similar to using !important. Here’s a great example of that technique.

But what if you don’t want the added specificity? Some developers suggest nesting selectors to get around it, but that can be less elegant to write.

Enter :where(). It works just like :is(), but with one major difference: it always has zero specificity—no matter what’s inside it. You can think of it as a specificity reset.

/* Specificity: 0 0 0 */
:where(h1, h2, h3, h4, h5, h6) {
  color: #BADA55;
}

/* Still specificity: 0 0 0 */
:where(h1, h2, h3, h4, h5, h6, #id) {
  color: #BADA55;
}

If you find that :is() is causing specificity issues in your styles, consider switching to :where(). It might be just what you need to keep your CSS clean and conflict-free.

Similar Posts