If you like me, you might come to get a quick overview to solve your specific problem, so here is a quick summary.
:is()
and :where()
are the same apart of one detail, their specificity is
different. The :where()
has a specificity value of 0 and :is()
would take the
most specific argument.
Both selectors can simplify your code. Let's say you want to highlight the first paragraph following any header title, but only if it is a paragraph and if it is following the header title.
1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | |
Here is an example of the same code using :is() selector.
1 | |
2 | |
3 | |
Here is how I would read those rules, starting from right to left: "Any P tag followed directly after any of H1..H6 tags will have color: lime".
Below is an example of a fancy way to target HTML elements which follow other elements
Fun fact: Apparently the original name for :is() was :matches(), which may give a hint as to what this selector does.
To summarise, the main benefit is that we can significantly improve the code by removing repetitive and long
lists of selectors. Chaining and combining :is()
, :where()
and :not()
we can select specific elements and reduce CSS boilerplate.
Firstly, :has()
can select a parent or previous sibling element which is simply amazing. It does
this by taking a selector list as an argument.
The specificity for :has()
is the same as per :is()
and :not()
Usage is similar to :is()
selector. Here is an example which adds special styling for paragraph
if it has an img
tag.
1 | |
2 | |
3 | |
4 | |
Simply put, this selector can select any parent element by the argument you pass into it.
For example, you can select any div
only if it has img
tag.
Also, you can combine it with :is()
and make powerful oneliners.
Below is an example where we select h1-h4 tags, and if the next direct sibling is from the has() list, it would receive a red colour.
1 | |
2 | |
3 | |
4 | |
5 | |
Try to create this without :has()
.
Who said that CSS is not a programming language?
Let's say you want to style the div
tag in special way, but only when there are em
and
code
tags. Not sure why you would do that, but for the sake of example, this is how you do it.
1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | |
10 | |
11 | |
To iterate, the first example is when both of the tags are available (AND), and the second is when any of the tags are available (OR)
Could we have self-aware boxes which would change the design based on the content? Oh, but we can! Take a look at the CSS example:
1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | |
10 | |
11 | |
12 | |
13 | |
14 | |
15 | |
16 | |
17 | |
18 | |
Each of those boxes will receive a different background colour based on the content in the boxes.
The :not()
is a negation pseudo-class and is probably most confusing from this post. There are
a few quirks to keep in mind.
Specificity is similar to :is()
but can increase as well. As per MDN:
"For example, #foo:not(#bar) will match the same element as the simpler #foo, but has the higher
specificity of two id selectors."
Usage is similar to :has()
. Add all the selectors you want to negate against as a comma-separated
list.
If you use it globally like this :not(.foo)
, it will match anything that is not .foo
including HTML and body tags
Example of :not()
usage.
1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | |