How to use the :is and :where CSS functions

Hey CSSLovers! These two functions are amazing! I'm talking about :is and :where. They both are pseudo-classes functions that are very handy if you're writing large selectors and want them to be in a more compact form.

According to MDN a Pseudo-class is a keyword added to a selector that specifies a special state of the selected element(s).

:is

This is basically a chaining selector that adds all the properties you want to different elements using the same line of code.

🤔 ???

Okay... This may sound a little bit confusing, let's take a look to a common situation:

  • We have a navigation that we need to add some styles.
  • We are trying to add a different color to the current active element.
  • Then we need to add a different color on hover and active states.
<nav class="players">
<ul>
<li class="player__bio active">Leo Messi</li>
<li class="player__bio">Jordi Alba</li>
<li class="player__bio">Sergio Busquets</li>
<li class="player__bio">Gerard Pique</li>
<li class="player__bio">Carles Puyol</li>
</ul>
</nav>

Traditional Way


  • [x] We are trying to add a different color to the current active element. (DONE)

I would add the following CSS:

.player__bio.active{
color: Crimson;
}

We only need to target the active element and change the default color.

  • [x] We are adding a different color on hover and active states. (DONE)

Let's keep playing with CSS:

.player__bio:hover,
.player__bio:focus
{
color: rebeccapurple;
}

I want you to notice that every time that we are trying to add the same style to the same element but on a different state we need to repeat the element selector, in this case .player__bio.

Ok Héctor, but that's easy to fix, did you know that there is something called CSS Preprocessors? 💡

Of course, I do know that! I just wanted to show you from the very basic, baby steps my friend, but I really LOVE Preprocessors, the one that I'm usually using is SASS.

.player__bio{
&:hover,
&:focus
{
color: rebeccapurple;
}
}

After we compile our SASS code, everything becomes the CSS version that we have above with two .player__bio classes.

So, What's the deal with :is?


Let's see how the :is selector works:

Simple, it takes a list of selectors as argument, and select those elements. 🙂

Let's take a look at the code:

.player__bio:is(:focus, :hover){
color: rebeccapurple;
}

🫠 WOW! The same result as above in just ONE line.

Do you have an idea of how handy is this? Let's check another example:

/* 3-deep (or more) unordered lists use a square */
ol ol ul, ol ul ul, ol menu ul, ol dir ul,
ol ol menu, ol ul menu, ol menu menu, ol dir menu,
ol ol dir, ol ul dir, ol menu dir, ol dir dir,
ul ol ul, ul ul ul, ul menu ul, ul dir ul,
ul ol menu, ul ul menu, ul menu menu, ul dir menu,
ul ol dir, ul ul dir, ul menu dir, ul dir dir,
menu ol ul, menu ul ul, menu menu ul, menu dir ul,
menu ol menu, menu ul menu, menu menu menu, menu dir menu,
menu ol dir, menu ul dir, menu menu dir, menu dir dir,
dir ol ul, dir ul ul, dir menu ul, dir dir ul,
dir ol menu, dir ul menu, dir menu menu, dir dir menu,
dir ol dir, dir ul dir, dir menu dir, dir dir dir
{
list-style-type: square;
}

Can be translated to this:

/* 3-deep (or more) unordered lists use a square */
:is(ol, ul, menu, dir) :is(ol, ul, menu, dir) :is(ul, menu, dir) {
list-style-type: square;
}

You see why I am so excited? For more information visit the MDN documentation here

... Have you heard about the term CSS specificity?

According to MDN, Specificity means:

Specificity is the means by which browsers decide which CSS property values are the most relevant to an element and, therefore, will be applied. Specificity is based on the matching rules which are composed of different sorts of CSS selectors.

What would happen if we use an ID in our :is function?

Guess?

You are totally right, It will increment the specificity and is going to override the rest.

Do not believe me 😁, let's look at an example:

.player__bio{
&:is(#ialwayswin,:hover, :focus){
color: peru; /* yes, there is a color name peru. */
}
}

.player__bio {
&:is(:hover, :focus) {
color: rebeccapurple;
}
}

Here is a Codepen link.

Let's use the following tool to calculate the specificity:

:is with the ID.

Specificity

:is without the ID.

Specificity

Please notice that event though the element with the ID #ialwayswin does not exists it increments significantly the specificity of the selector.

What about the :where function?

The only difference between the :is and :where functions is, 🎹chan chan chan🎹 SPECIFICITY!

The :where function receives the same parameters as :is but by default it adds Zero (0) specificity. This is important because gives the ability to easily override default values, think about JavaScript Plugins, WordPress Plugins, CSS resets, etc.

Example:

.player__bio{
&:hover,
&:focus
{
color: green;
}
}

.player__bio{
&:where(:focus, :hover) {
color: OrangeRed;
}
}

If the browser reads the CSS styles in order, what do you think would be the color for the .player__bio element?

OrangeRed or green

Let's analyze the specificity:

Specificity

Specificity

The winner is green.