CSS :not() Pseudo-class — Exclusion-Based Selection

Master the CSS :not() negation pseudo-class for selecting elements that do NOT match a given selector. Covers simple and complex :not() usage with forgiving selector lists.

Pseudo-classes

Detailed Explanation

CSS :not() Pseudo-class

The :not() pseudo-class selects elements that do not match the given selector argument. It is one of the most powerful tools for writing concise, maintainable CSS.

Syntax

/* Select all <p> elements that don't have the .intro class */
p:not(.intro) {
  font-size: 1rem;
}

CSS Selectors Level 3 vs Level 4

Level 3 (widely supported): Only simple selectors inside :not():

:not(.class) { }
:not(#id) { }
:not([attr]) { }
:not(:pseudo) { }

Level 4 (modern browsers): Complex selectors and comma-separated lists:

:not(.a, .b) { }
:not(.parent > .child) { }

Common Patterns

Apply styles to all but the last element:

li:not(:last-child) {
  border-bottom: 1px solid #eee;
}

Style all inputs except submit buttons:

input:not([type="submit"]):not([type="button"]) {
  border: 1px solid #ccc;
  padding: 0.5rem;
}

Remove margins from the first and last item:

.item:not(:first-child):not(:last-child) {
  margin: 1rem 0;
}

Specificity

The specificity of :not() is determined by the most specific argument inside it. :not(.foo) has specificity (0, 1, 0) (from .foo), not from :not itself.

Common Gotcha

:not(*) selects nothing (since every element is *). And :not() without an argument is invalid CSS.

Use Case

The :not() pseudo-class simplifies CSS by allowing exclusion patterns. Developers use it to add borders between items but not after the last one, apply styles to all form fields except submit buttons, target non-disabled interactive elements, exclude specific component variants from base styles, and reduce the need for override rules that reset previously applied styles.

Try It — CSS Selector Tester

Open full tool