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.
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:
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:
ℹ️ 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:
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()
:
ℹ️ 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()
:
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).
To see why this is important to keep in mind, let's consider the example below:
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).
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)
.
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.
Browsers compatibility
Both these functional pseudo-class selectors are supported by all evergreen browsers: source 🔗
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!