This content originally appeared on Manuel Matuzović - Blog and was authored by Manuel Matuzović
Thoughts on when it’s better to use :is()
over :where()
and vice versa.
The other day, I posted this code snippet on social media, asking people whether it was readable.
summary:where(:hover, :focus-visible)::after {
transform: rotate(180deg);
}
Some people responded they prefer :is()
over :where()
because it’s shorter or less typing. Others said they liked :where()
better because grammatically it made more sense to them or because it just sounded better.
These sound like valid reasons to pick one over the other, but they shouldn’t be (the main) reasons. As we already know, there is an important difference between :is() and :where(). The specificity of :where()
is always 0, while :is()
takes on the specificity of the most specific selector in its arguments.
I thought that was clear to me, but a brief discussion following my initial question made me realize that I needed to put a bit more thinking into the topic. Kilian asked me whether I find myself defaulting to :is()
or :where()
, and I responded “:where() because I like to keep the specificity curve as flat as possible”. Then Šime responded “But summary:hover
should have a higher specificity than summary
. That’s a good thing.”, and he's right!
The case for :is()
In the following example, I'm defining that the background color of the summary
should be blue and change to red on hover and focus.
summary:hover,
summary:focus-visible {
background-color: red;
}
summary {
background-color: blue;
}
You can see that the declaration for the default state of the element comes later in the document, but it doesn't overwrite the styles for the hover and focus states because its specificity is lower. I guess we can agree that it would make more sense to write it the other way around, but it's a good thing that it still works that way. The :hover
and :focus-visible
pseudo-classes make the selector more specific, because it's their job to define styles for a specific scenario.
Show more info
Here's the info
Now, let’s do the same using :where()
.
summary:where(:hover, :focus-visible) {
background-color: red;
}
summary {
background-color: blue;
}
Show more info
Here's the info
Now the background color is always blue because the specificity of the first and second selector is the same and the second selector, which comes later in the document, overwrites the styles of the first selector.
:where()
nulls the specificity of its selectors. While it’s a good practice to keep specificity low, sometimes we need higher specific to assure that certain rules will be applied.
This is an example where we want to maintain the specificity of the selectors, and we can do that by using :is()
.
summary:is(:hover, :focus-visible) {
background-color: red;
}
summary {
background-color: blue;
}
Show more info
Here's the info
The case for :where()
Sometimes we need selectors with higher specificity to improve readability and comprehensibility, or to limit the elements styles will be applied to.
For example, in your base styles you might have something like this.
input[type="text"],
input[type="email"],
input[type="url"] {
background-color: #efefef;
border: 2px solid;
}
<label for="name">name</label>
<input type="text" id="name">
Now, let's say you want to change the border color when the data provided by the user is invalid.
[aria-invalid="true"] {
border-color: red;
}
<label for="name">name</label>
<input type="text" id="name" aria-invalid="true">
The color of the border doesn't change because input[type="text"]
is more specific than [aria-invalid="true"]
. We don't need input[type="text"]
to be that specific, but the combination of tag and attribute selector makes it easier for us to understand what's going on and it rules out other elements which potentially might have a type
attribute with these values.
We can use :where()
to lower the specificity of the selector.
input:where(
[type="text"],
[type="email"],
[type="url"]) {
background-color: #efefef;
border: 2px solid;
}
[aria-invalid="true"] {
border-color: red;
}
Now [aria-invalid="true"]
(specificity of a class/attribute) overrules input:where(…)
(specificity of an element).
I will take Kilians and Šimes advice and use :is()
by default from now on because most of the time we need our complex selector to have a certain specificity. Only in exceptional cases, it's better to use :where()
to decrease the specificity.
My blog doesn't support comments yet, but you can reply via blog@matuzo.at.
This content originally appeared on Manuel Matuzović - Blog and was authored by Manuel Matuzović
Manuel Matuzović | Sciencx (2022-11-10T00:00:00+00:00) Day 34: :is() or :where(). Retrieved from https://www.scien.cx/2022/11/10/day-34-is-or-where-2/
Please log in to upload a file.
There are no updates yet.
Click the Upload button above to add an update.