DEV Community

Cover image for CSS the :not() selector
Kars van Iersel
Kars van Iersel

Posted on • Edited on • Originally published at karsvaniersel.com

CSS the :not() selector

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) {

}
Enter fullscreen mode Exit fullscreen mode

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) {

}
Enter fullscreen mode Exit fullscreen mode

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;
}
Enter fullscreen mode Exit fullscreen mode

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;
}
Enter fullscreen mode Exit fullscreen mode

Or use it with :nth-child()

li:not(:nth-child(2)) {
  margin: 20px 0;
}
Enter fullscreen mode Exit fullscreen mode

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)

Collapse
 
alohci profile image
Nicholas Stimpson

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.