CSS Reference Pseudo-class


: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:

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.


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.

View this demo on the Codrops Playground

Browser Support

The :not() pseudo-class selector is supported in Chrome, Firefox, Safari, Opera 9.5+, Internet Explorer 9+, and on Android and iOS.

Written by

Last updated February 3, 2015 at 12:33 pm by Mary Lou

Do you have a suggestion, question or want to contribute? Submit an issue.