:not()
: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 article
s 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.