CSS :not() Pseudo-Class

The CSS :not() pseudo-class selects elements that do not match a specified selector. It is useful when most elements in a group should receive a style but one or more elements need to be excluded.

The :not() Pseudo-Class

The :not() pseudo-class places the selector to exclude inside its parentheses.

p:not(.intro) {
  color: #777777;
}

The selector p:not(.intro) matches <p> elements that do not have the intro class.

How :not() Works

The selector before :not() identifies the elements to consider, while the selector inside the parentheses identifies which of those elements should be excluded.

<p class="intro">Introduction paragraph.</p>
<p>Regular paragraph.</p>
<p>Another regular paragraph.</p>
p:not(.intro) {
  color: #0088cc;
}

The two regular paragraphs match because they do not have the intro class. The first paragraph is excluded because it matches .intro.

Excluding a Class

One of the simplest uses of :not() is excluding elements that have a particular class.

li:not(.current) {
  color: #777777;
}

li.current {
  color: #0088cc;
  font-weight: bold;
}
<ul>
  <li>HTML</li>
  <li class="current">CSS</li>

  <li>JavaScript</li>
</ul>
Browser Result
  • HTML
  • CSS
  • JavaScript

The first and third list items match li:not(.current). The second item is excluded because it has the current class.

Excluding an Attribute

The selector inside :not() can also be an attribute selector. This makes it possible to select elements that do not have a particular attribute or attribute value.

input:not([required]) {
  background-color: #f5f5f5;
}
<input type="text" name="first-name" required>
<input type="text" name="middle-name">

The second input matches because it does not have the required attribute. The first input is excluded.

Using :not() with Structural Pseudo-Classes

The :not() pseudo-class can be combined with structural pseudo-classes. A common example is applying spacing or separators to every item except the last one.

li:not(:last-child) {
  margin-bottom: 10px;
}

Every <li> except the last child receives the bottom margin. This is useful when spacing or a separator is needed between items but not after the final item.

li:not(:first-child) {
  border-top: 1px solid #dddddd;
}

This selector applies a top border to every matching list item except the first child.

Excluding Multiple Selectors

The :not() pseudo-class can contain a selector list, allowing several selectors to be excluded at the same time.

p:not(.intro, .note) {
  color: #777777;
}
<p class="intro">Introduction.</p>
<p>Regular paragraph.</p>
<p class="note">Important note.</p>
<p>Another regular paragraph.</p>

The regular paragraphs match, while paragraphs with either the intro or note class are excluded.

Keeping :not() Selectors Readable

The :not() pseudo-class can make selectors concise, but complicated exclusions can also make CSS harder to understand. For beginner CSS, it is usually best to keep the selector inside :not() simple and use it when the exclusion makes the rule easier to read.

.menu li:not(.current) {
  color: #777777;
}

This selector clearly communicates that list items inside .menu should be styled unless they have the current class.

If a selector requires several complicated exclusions to explain which elements should match, using a class directly may produce CSS that is easier to maintain.

When to Use :not()

Use :not() when a group of elements should receive the same styles except for elements that match a particular selector. Common uses include excluding a class, excluding elements with an attribute, or leaving the first or last item out of a repeated style.

The pseudo-class is especially useful when the HTML already contains enough information to identify the exception and adding another class solely for CSS would be unnecessary.