Intro
In my previous post
I wrote a bit about the :not()
selector and I got a lot feedback that people never heard of this element. So I figured I would dedicate a post just to the :not()
CSS selector.
What is the :not() selector in CSS?
The :not()
is a CSS pseudo-class that targets elements that do not match the selector given. Since it prevents specific items from being selected, it is known as the negation pseudo-class.
In essence you can target anything except what you put in the :not()
selector.
Lets look at a quick example:
:not() rules
There are a couple of rules when using the :not()
selector. You should keep this in mind when using the :not()
selector in your projects, cause they could cause unsual outcomes that have you burn hours trying to figure them out.
- You cannot nest the
:not()
pseudo-class, which means you cannot do:not(:not(...))
- You cannot use it with pseudo-elements such as
::before
and::after
. It will work with:first-child
and:last-child
since they are simple selectors. - Using the
:not()
selector can increase the specificity of a rule.#foo:not(#bar)
will match the same element as the simpler#foo
but with a higher specificity. - Using just
:not(.class)
will match anything that isn't.class
including<html>
and<body>
. - The
:not()
selector only applies to one element; you cannot use it to exclude all ancestors.body :not(table) a
will still apply to links inside of a table, since<tr>
will amtch with the:not()
How to use the :not() selector with multiple classes
It is possible to use the :not()
selector with multiple classes.
Normally you would just want to do:
p:not(.foo) {
}
But maybe you want to avoid multiple classes? There are no real combinators with :not()
and you cannot nest them. But you can chain them, which works similar to and
.
p:not(.foo):not(.bar):not(.bold):not(.italic) {
}
Tricks with :first-child, :last-child and :nth-child()
I use the :not()
CSS selector most often with the :first-child
or :last-child
pseudo-class.
Think of having a list that you want to add some spacing to, but you don't want to last item to also have spacing at the bottom right? Well with :not()
that is super easy to solve!
li:not(:last-child) {
margin-bottom: 20px;
}
This CSS will be applied to all <li>
elements except the last child.
You could also do the reverse with :first-child
li:not(:first-child) {
margin-top: 20px;
}
Or use it with :nth-child()
li:not(:nth-child(2)) {
margin: 20px 0;
}
Here is a quick codepen sample to see it in action:
Conclusion
A lot of handy things can be achieved by using the :not()
CSS selector. I know I use it a lot of times, for menus, list items and what not. Even flexbox grids!
I hope you learned something from this post, and hopefully you can enhance your CSS skills with this knowledge.
Let me know how you apply the :not()
selector, I'm always eager to new learn tricks with it.
Top comments (1)
You should clarify the point about specificity.
:not()
is unusual compared to traditional pseudo-classes in having no specificity of its own, using that of its parameter instead. So#foo:not(#bar)
has a specificity of 0,2,0,0 rather than 0,1,1,0. The newer:is()
and:where()
pseudo-classes similarly have specialised specificity rules.