:not() is a CSS negation pseudo-class selector. It is a functional pseudo-class selector that takes a simple selector as an argument, and then matches one or more elements that are not represented by the argument.
The simple selector that :not() takes as an argument can be any of the following:
- Type selector (e.g
p,span, etc.) - Class selector (e.g
.element,.sidebar, etc.) - ID selector (e.g
#header) - Pseudo-class selector (e.g
:first-child,:last-of-type) - Attribute selector (e.g
[type="checkbox"]) - The universal selector (
*)
The argument passed to :not() can not, however, be a pseudo-element selector (such as ::before and ::after, among others) or another negation pseudo-class selector.
So, the following are invalid :not() values:
/* INVALID */
p:not(:not(.same)) {}
p:not(:not(:last-child)) {}
:not(::first-letter) {}
a:not(::after) {}
So :not() cannot be nested (:not(:not(..))), and it also cannot be nested inside the :matches() pseudo-class selector (:matches(:not(..))).
As mentioned before, the :not() selector matches an element that is not represented by the selector in its argument. So, this rule:
li:not(.new) {
/* style all list items except the ones that have the class new */
}
will select all list items except those that have a class name .new.
The :not() selector is chainable with more :not() selectors. For example, the following will match all articles except the one with an ID #featured, and then will filter out the articles with a class name .tutorial:
article:not(#featured):not(.tutorial) {
/* style the articles that match */
}
You can also use the :not() selector “globally”, without applying it to an element, thus selecting all elements in a document that are not represented in the argument. For example:
:not(a) {
color: #333;
}
Just like other pseudo-elements and pseudo-class selectors, :not() can be chained with other pseudo-classes and pseudo-elements. For example, the following will add a “New!” word to list items that do not have a .old class name, using the ::after pseudo-element:
li:not(.old)::after {
content: "New!";
color: deepPink;
}
You can see a live demo in the Live Demo section below.
On the Specificity of selectors
The specificity of the :not() pseudo-class is the specificity of its argument. The :not() pseudo-class does not add to the selector specificity, unlike other pseudo-classes.
Trivia & Notes
The :not() pseudo-class selector allows useless selectors to be written. For instance :not(*), which represents no element at all will never apply any styles, or foo:not(bar) (e.g p:not(article)), which is equivalent to foo but with a higher specificity.
And since you can use :not() globally and select all elements that are not represented by the argument, you should also note that :not(X) will match anything that isn’t X, including html and body.
Future levels of CSS (Level 4) will allow using selector lists inside :not(), such as .title:not(h1, h2) and :not(#ID, .classname), for example, and more complex selector combinations. This entry will be updated when that happens.
Examples
The following are all valid :not() declarations:
:not(a) {
/* select all elements except anchor tags */
}
p:not(:first-of-type) {
/* styles applied to all paragraphs except the first paragraph in a list of siblings */
}
a:not([href = "http://codrops.com"]) {
/* styles all link except the ones linking to http://codrops.com */
}
input[type="text"]:not([disabled="disabled"]) {
/* styles all text inputs that are not disabled */
}
h1:not(#page-title) {
/* styles all h1 except the #page-title */
}
Live Demo
The following demo styles all list items except the ones that have a .old class.
Browser Support
The :not() pseudo-class selector is supported in Chrome, Firefox, Safari, Opera 9.5+, Internet Explorer 9+, and on Android and iOS.