:not

Avatar of Sara Cope
Sara Cope on (Updated on )

The :not() property in CSS is a negation pseudo class and accepts a simple selector or a selector list as an argument. It matches an element that is not represented by the argument. The passed argument may not contain additional selectors or any pseudo-element selectors.

The ability to use a list of selectors as an argument is considered experimental, although its supported is growing at the time of this writing, including Safari (since 2015), Firefox (since December 2020), and Chrome (since January 2021).

/* the X argument can be replaced with any simple selectors */
:not(X) {
  property: value;
}

In this example we have an unordered list with a single class on the <li>:

<ul>
  <li></li>
  <li class="different"></li>
  <li></li>
</ul>

Our CSS would select all the <li> elements except the one(s) with a class of .different.

/* Style everything but the .different class */
li:not(.different) {
  font-size: 3em;
}

You could also do the same using pseudo classes which are considered a simple selector.

p:not(:nth-child(2n+1)) {
  font-size: 3em;
}

However, if we use a pseudo-element selector as our argument it will not produce the expected result.

:not(::first-line) { /* ::first-line is a pseudo element selector and not a simple selector */
  color: white;
}

Complex selectors

These are newer than the basic :not() selectors.

/* select all <p>s that are not descendants of <article> */
p:not(article *) {

}

This can get a little mind-bending with just a bit more nesting. For example:

h2:not(:where(article *, section *)) {
  ... 
}

/*
<article>
  <h2> No match! </h2>
</article>

<section>
  <h2> No Match! </h2>
</section>

<aside>
  <h2> Match! </h2>
</aside>
*/

Visual example

Visual representation of the varied uses of :not()

Specificity

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. 

Negations may not be nested so :not(:not(...)) is never permitted. Authors should also note that since pseudo-elements are not considered a simple selector, they are not valid as an argument to :not(X). Be mindful when using attribute selectors as some are not widely supported as others. Chaining :not selectors with other :not selectors is permissible.

Browser support

The :not() pseudo class has been updated in the CSS Selectors Level 4 specification to allow an argument list. In CSS Selectors Level 3, it was only capable of accepting a single simple selector. As a result, browser support is a little divided between the Level 3 and Level 4 drafts.

Simple selectors

IEEdgeFirefoxChromeSafariOpera
9+AllAllAll12.1+All
Android ChromeAndroid FirefoxAndroid BrowseriOS SafariOpera Mobile
AllAllAllAllAll

Selector lists

This browser support data is from Caniuse, which has more detail. A number indicates that browser supports the feature at that version and up.

Desktop

ChromeFirefoxIEEdgeSafari
8884No889

Mobile / Tablet

Android ChromeAndroid FirefoxAndroidiOS Safari
1231241239.0-9.2

More information