css selectors ":not()"

The :not() CSS pseudo-class represents elements that do not match a list of selectors. Since it prevents specific items from being selected, it is known as the negation pseudo-class.

The :not() pseudo-class has a number of quirks, tricks, and unexpected results that you should be aware of before using it.

Syntax

The :not() pseudo-class requires a comma-separated list of one or more selectors as its argument. The list must not contain another negation selector or a pseudo-element.

:not(<complex-selector-list>) {
  /* ... */
}

Description

There are several unusual effects and outcomes when using :not() that you should keep in mind when using it:

Examples

Using :not() with valid selectors

This example shows some simple cases of using :not().

HTML

<p>I am a paragraph.</p>
<p class="fancy">I am so very fancy!</p>
<div>I am NOT a paragraph.</div>
<h2>
  <span class="foo">foo inside h2</span>
  <span class="bar">bar inside h2</span>
</h2>

CSS

.fancy {
  text-shadow: 2px 2px 3px gold;
}

/* <p> elements that don't have a class `.fancy` */
p:not(.fancy) {
  color: green;
}

/* Elements that are not <p> elements */
body :not(p) {
  text-decoration: underline;
}

/* Elements that are not <div>s or `.fancy` */
body :not(div):not(.fancy) {
  font-weight: bold;
}

/* Elements that are not <div>s or `.fancy` */
body :not(div, .fancy) {
  text-decoration: overline underline;
}

/* Elements inside an <h2> that aren't a <span> with a class of `.foo` */
h2 :not(span.foo) {
  color: red;
}

Using :not() with invalid selectors

This example shows the use of :not() with invalid selectors and how to prevent invalidation.

HTML

<p class="foo">I am a paragraph with .foo</p>
<p class="bar">I am a paragraph with .bar</p>
<div>I am a div without a class</div>
<div class="foo">I am a div with .foo</div>
<div class="bar">I am a div with .bar</div>
<div class="foo bar">I am a div with .foo and .bar</div>

CSS

/* Invalid rule, does nothing */
p:not(.foo, :invalid-pseudo-class) {
  color: red;
  font-style: italic;
}

/* Select all <p> elements without the `foo` class */
p:not(:is(.foo, :invalid-pseudo-class)) {
  color: green;
  border-top: dotted thin currentcolor;
}

/* Select all <div> elements without the `foo` or the `bar` class */
div:not(.foo, .bar) {
  color: red;
  font-style: italic;
}

/* Select all <div> elements without the `foo` or the `bar` class */
div:not(:is(.foo, .bar)) {
  border-bottom: dotted thin currentcolor;
}

Result

The p:not(.foo, :invalid-pseudo-class) rule is invalid because it contains an invalid selector. The :is() pseudo-class accepts a forgiving selector list, so the :is(.foo, :invalid-pseudo-class) rule is valid and equivalent to :is(.foo). Thus, the p:not(:is(.foo, :invalid-pseudo-class)) rule is valid and equivalent to p:not(.foo).

If :invalid-pseudo-class was a valid selector, the first two rules above would still be equivalent (the last two rules showcase that). The use of :is() makes the rule more robust.

See also