:where :is CSS?
Tags: css, webdev, beginners, tutorial
Published: 2022-10-10 08:45:05

In this post we will talk about the not so new functional pseudo-class selectors `:is()` and `:where()`.

We will see how they work in details, how they differ and when to use them to get the most out of these CSS features.




&nbsp;
## 1. CSS :is

Let's start by the `:is()` pseudo-class selector. Then we will talk about `:where()` and the difference between them.



### What is `:is()`?

Originally named `:matches()` and `:any()`, `:is()` is a functional pseudo-class selector. Meaning it is a keyword recognized by CSS that consists of a colon (:) followed by the pseudo-class name and a pair of parenthesis to define the arguments.

`:is()` takes as an argument a selector list separated by a comma and selects any element that can be selected by one of the selectors in that list. Let's see some use-cases.

### Targeting parents

Suppose that we need to set the `font-size` of every paragraph element (`<p>`) located in a `<section>` or an `<article>`, we can use `:is()` to write that in a more compact form:


![Image 2](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/qtx62pcw1ufdx8ra5mlg.png)

Of course, in this example, we only removed one line, but we'll see later that we can remove much more using this to write more compact code.


### Targeting children

Now let's say we need to target every `<b>` and `<strong>` inside an `<article>` to set their `font-weight` property, here's how we can use `:is()` to do it:


![Image 3](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/u4n34zwdjpk9g58ofm8g.png)

| ℹ️ Note                                                                                                              |
|---------------------------------------------------------------------------------------------------------------------|
| Notice the space between `article` and `:is`. It's important to keep it. We will talk about it further in the post. |


### Combining multiple `:is()`

If we wanted to target every every `<b>` and `<strong>` located inside a `p` or `span` that is located inside an `<article>` or a `section` it would look like this:


![Image 4](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/rw7suy28052m6yp1zvm0.png)

In the example above we can see that it makes the code much more concise. It also makes it more readable and easier to maintain in my opinion.



### Applying `is()` to the current element

Like we saw before, the space between before `:is()` is important. If we remove it, to have something like this: `article:is(b)` we would be asking for an `article` element that is also a `b` element witch is impossible.

We could use `:is()` to check if an element is for exemple the `first-child` or `last-child` in witch case we don't put the space before the `:is()`:


![Image 5](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/l8ja5m8duykqbqv4js0z.png)

| ℹ️ Note                                                                                                              |
|---------------------------------------------------------------------------------------------------------------------|
| `:is()` does not select pseudo-elements. Meaning `some-element:is(::before, ::after)` will not work. |


### `is()` is forgiving

Typically, if any of the selectors in a comma-separated list are invalid, all of them will be invalid and the entire expression will fail to match anything. This is not the case while using `is()`:


![Image 6](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ya6op7kb14e03qjuuaxe.png)


### Specificity

`:is()` takes the specificity of its most specific selector. This means that `:is(p, .some-class, #some-id)` will have a specificity score of an ID (100 points) and `:is(p, .some-class)`will have specificity score of a class (10 points).

![Image 7](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/gyez6imv4762w9cga3ng.png)


To see why this is important to keep in mind, let's consider the example below:


![Image 7.5](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/idoq0e5k3jbx36o3jyxr.png)

The rectangle above is orange because the specificity score of `.wrapper .rect` is 20 while the specificity score of `:is(.rect, #some-id)` is equal to the specificity of its most specific selector which is `#some-id` (100 points). 



&nbsp;
## 2. Every :where

Now that we are familiar with the `is()` pseudo-class selector, let's talk about `where()`.

### What is `:where()`?

`where()` is also a functional pseudo-class selector and works like `is()`. It takes as an argument a selector list separated by a comma and selects any element that can be selected by one of the selectors in that list. We can use it to target elements like we did with `is()` and it is also forgiving. 

So why does it exists if it works the same as `is()`? 
Well, because it doesn't work *exactly* the same.

### The difference

The only difference is that the specificity of `:where()` is always zero. That's it.

So, if we take our previous examples, `:where(p, .some-class, #some-id)` will have a specificity score of zero. The same for `:where(p, .some-class)`.


![Image 8](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/joz1ltlyext805wbbgec.png)


### When to use it?

Every time you want to keep the specificity low, which I think is a good thing to do most of the time. 
So, for example, using `:where()` you can easily target an element by its ID without messing the specificity.




&nbsp;
## Browsers compatibility

Both these functional pseudo-class selectors are supported by all evergreen browsers:
![Browsers compatibility](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/lmjwe28pmbkbxaadm4n0.png)
<sub>[source 🔗](https://caniuse.com/css-matches-pseudo)</sub>


&nbsp;
&nbsp;
## Wrap up

That's it for this post. We saw how to use `:is` & `:where` and the difference between them. But before you go and rewrite your entire CSS code base, remember that **readability is what your team is used to**, so it might be a good idea to discuss this before :)

Cheers!