csscss-selectors

What is the difference between :where() and :is()?


CSS recently added the pseudo-classes :where() and :is() and I don't understand when to use which. Both can be used to select multiple elements. Here is a snippet where the same is achieved with both pseudo-classes:

span {
  display: inline-block;
  height: 100px;
  width: 100px;
  background-color: grey;
  margin-bottom: 10px;
}

:is(.span1-1, .span1-2):hover {
  background-color: firebrick;
}

:where(.span2-1, .span2-2):hover {
  background-color: teal;
}
<span class="span1-1"></span>
<span class="span1-2"></span>
<br>
<span class="span2-1"></span>
<span class="span2-2"></span>

Can someone give an example where they behave differently from each other?


Solution

  • Explaining :is vs :where for those unfamiliar with CSS specificity:

    Specificity is written as 3 numbers, and is of the form ID-CLASS-TYPE

    For example:

    #thing .my-class div has specificity 1-1-1

    #thing .my-class div:hover has specificity 1-1-2 (pseudo classes are considered a type)

    .my-class .my-other-class has specificity 0-2-0

    #thing has specificity 1-0-0

    div has specificity 0-0-1

    To determine CSS rule priority, the specificities of rules are compared. Each of the 3 numbers are compared against other rules, letting the left-most comparison win.

    For example, 0-2-0 wins against 0-1-3, and 1-0-0 wins against 0-2-0.

    Now, to answer the question, :is is useful to avoid repetition, so that you can write the rule ul li, ol li as :is(ul, ol) li

    Note that :is is not itself counted as a pseudo-class for the purposes of calculating the specificity of the rule.

    :where lets you do exactly the same thing as :is, except the rules mentioned inside the :where() parentheses are not counted towards a rule's specificity calculation.

    For example, :is(ul, ol) li has specificity 0-0-2, but :where(ul, ol) li has specificity 0-0-1.

    You will only need to worry about your choice of where vs is if you find yourself in a situation where you need to consider the priorities of two similar CSS rules.

    Note that any use of !important will take priority over any specificity comparisons.