CSS :not() Pseudo-Class

The CSS :not() pseudo-class, also called the negation pseudo-class, matches elements that do not match a specified selector or selector list. It allows developers to exclude particular elements, classes, attributes, or states from a CSS rule without adding extra classes to the HTML.

:not() Syntax

selector:not(argument) {
  property: value;
}

The :not() pseudo-class accepts a selector or a comma-separated list of selectors. The element must match the selector outside :not() and must not match any selector inside it.

Basic Example

p:not(.highlight) {
  color: #333;
}

This rule selects paragraph elements that do not have the highlight class.

Multiple Selectors

p:not(.highlight, .warning) {
  color: #333;
}

This rule selects paragraphs that have neither the highlight class nor the warning class.

Functional Pseudo-Class

The parentheses are required because :not() is a functional pseudo-class. Its argument must be a valid selector list.

Selector List Behavior

The argument uses a regular, unforgiving selector list. If any selector in the list is invalid or unsupported, the entire selector can become invalid. To tolerate unsupported alternatives, use :is() or :where() where appropriate.

How :not() Works

The :not() pseudo-class filters elements out of an existing selector match.

HTML Example

<p>Regular paragraph</p>
<p class="highlight">Highlighted paragraph</p>
<p>Another regular paragraph</p>

CSS Example

p:not(.highlight) {
  color: #006699;
}

The first and third paragraphs match the selector. The second paragraph is excluded because it has the highlight class.

Matching Process

The browser first considers paragraphs matching p. It then excludes any paragraph that matches .highlight.

No HTML Changes Required

The exclusion is determined by CSS. You do not need to add a separate class to every paragraph that should receive the styling.

Not a JavaScript Filter

The pseudo-class affects CSS selector matching. It does not remove elements from the document or change their HTML attributes.

Excluding Classes

One of the most common uses of :not() is to style elements that do not have a particular class.

CSS Example

.button:not(.disabled) {
  background-color: #006699;
  color: #fff;
}

This rule selects elements with the button class unless they also have the disabled class.

HTML Example

<button class="button">Save</button>
<button class="button disabled">Unavailable</button>

Only the first button matches the selector.

Class vs. Disabled State

A class named disabled does not disable a button's behavior. For actual disabled form controls, use the HTML disabled attribute and the :disabled pseudo-class.

button:not(:disabled) {
  cursor: pointer;
}

This rule targets buttons that are not disabled.

Excluding Element Types

The :not() pseudo-class can exclude specific HTML element types.

CSS Example

article > :not(h2) {
  margin-top: 12px;
}

This rule selects direct children of an article except <h2> elements.

HTML Example

<article>
  <h2>Article Heading</h2>
  <p>First paragraph.</p>
  <p>Second paragraph.</p>
</article>

The paragraphs match the selector, while the heading is excluded.

Exclude Multiple Element Types

article > :not(h2, h3) {
  margin-top: 12px;
}

This rule excludes both second-level and third-level headings.

Universal Matching

When :not() is used without a preceding type selector, it can match any eligible element that does not match the excluded selector.

Multiple Selectors

Selectors Level 4 allows :not() to accept multiple selectors separated by commas.

CSS Example

li:not(.active, .disabled, .hidden) {
  color: #006699;
}

This rule selects list items that do not have any of the three excluded classes.

Equivalent Selector

li:not(.active):not(.disabled):not(.hidden) {
  color: #006699;
}

Both selectors match the same elements, although their specificity differs.

Important Rule

An element is excluded if it matches any selector in the argument list. It must fail to match every listed selector to satisfy :not().

Browser Compatibility

Older browsers that support only the original single-selector form may not support comma-separated selector lists inside :not().

Excluding Attributes

The :not() pseudo-class can be combined with attribute selectors to exclude elements based on their attributes.

Links Without target

a:not([target]) {
  color: #006699;
}

This rule selects anchor elements that do not have a target attribute, including anchors without an href attribute.

Inputs Without required

input:not([required]) {
  border-color: #999;
}

This rule selects input elements without the required attribute.

Exclude a Specific Attribute Value

input:not([type="hidden"]) {
  border: 1px solid #ccc;
}

This rule excludes input elements whose type attribute is explicitly set to hidden.

Multiple Attribute Conditions

input:not([disabled], [readonly]) {
  background-color: #fff;
}

This rule selects input elements that have neither the disabled nor the readonly attribute.

Excluding Element States

The :not() pseudo-class can exclude elements based on other pseudo-class states.

Enabled Buttons

button:not(:disabled) {
  background-color: #006699;
  color: #fff;
}

This rule selects buttons that are not disabled.

Unchecked Checkboxes

input[type="checkbox"]:not(:checked) {
  outline: 1px solid #999;
}

This rule selects checkboxes that are not checked.

Elements Not Being Hovered

.card:not(:hover) {
  box-shadow: none;
}

This rule applies while a card is not being hovered.

Invalid Inputs

input:not(:valid) {
  border-color: #cc3333;
}

This rule selects inputs that do not match :valid. For form controls, :invalid is usually clearer when the goal is to style invalid values.

Complex Selectors and Combinators

Selectors Level 4 allows complex selectors inside :not(), including selectors that contain combinators.

Descendant Selector

p:not(article p) {
  color: #006699;
}

This rule selects paragraphs that are not descendants of an <article> element.

Child Combinator

p:not(section > p) {
  margin-bottom: 16px;
}

This rule excludes paragraphs that are direct children of a <section> element.

Combining Conditions

.content p:not(.intro, .note) {
  line-height: 1.6;
}

This rule selects paragraphs inside .content except those with the intro or note class.

Browser Support

Complex selectors inside :not() are a newer capability than the original single simple selector syntax. Test compatibility when supporting older browsers.

Nested :not() Selectors

The :not() pseudo-class can contain another :not() pseudo-class.

CSS Example

p:not(:not(.highlight)) {
  color: #006699;
}

This double negation selects paragraphs with the highlight class.

Equivalent Selector

p.highlight {
  color: #006699;
}

The simpler selector is easier to read and produces the same matches.

Multiple Negations

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

This rule selects paragraphs that have neither the intro class nor the note class.

Readability

Avoid unnecessary nested negations. Use direct selectors whenever they express the intended condition more clearly.

:not() vs. :is() and :where()

These functional pseudo-classes accept selector lists but have different matching and specificity behavior.

Comparison

Pseudo-Class Behavior
:not() Matches elements that do not match any selector in its argument list.
:is() Matches elements that match at least one selector in its argument list.
:where() Matches like :is() but contributes zero specificity.

CSS Example

p:not(.intro, .note) {
  color: #333;
}
:is(h2, h3) {
  color: #006699;
}
:where(h2, h3) {
  margin-bottom: 12px;
}

The first rule excludes paragraphs with particular classes. The second and third rules match selected heading types.

Choosing a Selector

Use :not() to exclude matches, :is() to group matching alternatives, and :where() when grouping selectors without increasing specificity.

:not() Specificity

The :not() pseudo-class does not add its own specificity. Its specificity is determined by the most specific selector in its argument list.

Specificity Examples

Selector Specificity
:not(p)0-0-1
p:not(.intro)0-1-1
p:not(.intro, #featured)1-0-1
li:not(:first-child)0-1-1
p:not(.intro):not(.note)0-2-1
p:not(:where(.intro, .note))0-0-1

Important Detail

p:not(.intro, #featured) {
  color: #006699;
}

The ID selector in the argument list gives this selector ID-level specificity, even when an element is excluded only because it does not match either argument.

Reducing Specificity

p:not(:where(.intro, #featured)) {
  color: #006699;
}

Wrapping the exclusions in :where() allows the exclusion logic to remain while reducing the specificity contributed by the argument to zero.

Practical Uses

The :not() pseudo-class is useful when most elements should receive a style but certain elements need to be excluded.

Exclude the Last Item

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

Add separators between list items without adding a border to the last item.

Exclude a Featured Card

.card:not(.featured) {
  background-color: #f5f5f5;
}

Apply a standard background to cards except the featured card.

Exclude Disabled Controls

button:not(:disabled) {
  cursor: pointer;
}

Apply a pointer cursor only to buttons that are not disabled.

Exclude Specific Input Types

input:not([type="checkbox"], [type="radio"]) {
  padding: 8px;
}

Apply padding to input elements except checkboxes and radio buttons.

Exclude Introductory Paragraphs

article p:not(.lead) {
  font-size: 1rem;
}

Apply standard text sizing to paragraphs except those marked as lead paragraphs.

Limitations

The :not() pseudo-class is powerful, but its matching behavior and specificity require care.

It Does Not Remove Elements

The pseudo-class excludes elements from a CSS selector match. It does not remove elements from the DOM or hide them automatically.

Selector Lists Must Be Valid

Invalid selector syntax can affect matching. Browser support for newer selector-list features also varies.

Pseudo-Elements Are Not Allowed

Pseudo-elements such as ::before and ::after cannot be used as arguments to :not().

Specificity Can Increase

An ID selector inside :not() can increase specificity even when the matched element does not have that ID.

Broad Selectors Can Match Unexpected Elements

:not(p) {
  color: #006699;
}

This rule matches every eligible element that is not a paragraph, including elements such as <html>, <body>, headings, and links.

Not a Parent Selector by Itself

The :not() pseudo-class does not independently select a parent based on its children. Combine it with :has() when a relationship-based exclusion is needed.

Best Practices

  • Use :not() when excluding a small number of elements from a broader selector.
  • Include an appropriate type or class selector to avoid matching unintended elements.
  • Use comma-separated selector lists when they improve readability and browser support is sufficient.
  • Remember that :not() uses the specificity of its most specific argument.
  • Use :where() inside :not() when low specificity is desirable.
  • Avoid unnecessary nested negations and overly complex selector chains.
  • Use state pseudo-classes such as :disabled instead of classes when selecting actual element states.
  • Do not use pseudo-elements as arguments to :not().
  • Test complex selector lists when supporting older browsers.

:not() Example

This example displays four cards. The :not() pseudo-class applies a light blue background and blue border to cards that do not have the featured or disabled class.

HTML

<div class="not-demo">
  <div class="card">Standard Card One</div>
  <div class="card featured">Featured Card</div>
  <div class="card">Standard Card Two</div>
  <div class="card disabled">Disabled Card</div>
</div>

CSS

.not-demo .card {
  padding: 12px;
  margin-bottom: 8px;
  border: 2px solid #ccc;
  background-color: #f5f5f5;
}
.not-demo .card:not(.featured, .disabled) {
  border-color: #006699;
  background-color: #eaf6fc;
  color: #006699;
}
.not-demo .card.featured {
  border-color: #cc9900;
  background-color: #fff5d6;
}
.not-demo .card.disabled {
  opacity: 0.5;
}

Browser Result

Play in Editor

Note: Standard Card One and Standard Card Two receive the blue styling. The Featured Card and Disabled Card are excluded from the :not() rule and retain their separate styles.

Browser Support

Baseline: Widely available. The :not() pseudo-class is supported in all major modern browsers. The original single simple selector syntax has long-standing support, while comma-separated selector lists and complex selectors were introduced in Selectors Level 4 and require more recent browser versions.

For current compatibility information, visit Can I Use? .

Specifications

The :not() pseudo-class is defined in CSS Selectors Level 4 as the negation pseudo-class. It accepts a selector list and matches elements that do not match any of its arguments.

Selectors Level 4 - Negation Pseudo-Class