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
::beforeand::after. It will work with:first-childand:last-childsince 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#foobut with a higher specificity. - Using just
:not(.class)will match anything that isn't.classincluding<html>and<body>. - The
:not()selector only applies to one element; you cannot use it to exclude all ancestors.body :not(table) awill 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.