CSS :not() with Multiple Classes | CSS-Tricks (2023)


Chris Coyier on

DigitalOcean provides cloud products for every stage of your journey. Get started with $200 in free credit!

Say you want to select an element when it doesn’t have a certain class. That’s what the :not() selector is for.

body:not(.home) { }

But what if there are multiple classes you want to avoid?

There are no logical combinators with :not(), like and or or, but you can chain them, which is effectively like and.

body:not(.home):not(.away):not(.page-50) { }

The :not() selector doesn’t add any specificy by itself, but what is inside does, so :not(.foo) adds the same weight as .foo does.

Psst! Create a DigitalOcean account and get $200 in free credit for cloud-based hosting and services.

    • Adam Taylor

      Permalink to comment#

      Since this will be the same behaviour as chaining them, we can probably expect build tools to automatically convert between them in the future.

      Thanks for the info!

  1. Matthew

    (Video) The new CSS pseudo-classes explained - :is() :where() :has()

    Permalink to comment#

    Thanks…dint know this was possible, giving it a try now.

  2. Kyle

    Permalink to comment#

    I think it goes without saying but having chained (:not)s just seems logically confusing. If 2 are checked for :not, then every class would be allowed. But there is clearly an additional layer of logic put into this pseudo class to make sure that a :not chain is self aware of the previous classes on the declaration.

    Oh well, good to know anyway!

  3. Mattia

    Permalink to comment#

    You should also mention that with Selectors 4 spec (link) we can pass a selectors list inside the :not() function. Like :not(h1, h2, h3)

  4. Thomas Luzat

    Permalink to comment#

    On first read, I found the and/or part a bit confusing, but this is basically using logical “and” to represent “or”: not(A or B) <=> not(A) and not(B). This also means that you can replace all “or” (represented in CSS by “,”) with a similar construct using “:not”:

    foo, bar { color: orange; }

    is (apart from specificity) equivalent to:

    :not(:not(foo):not(bar)) { color: orange; }

    Not sure if that is helpful in any context (where selector lists may not be allowed?).

  5. Thomas Luzat

    Permalink to comment#

    Kyle, it doesn’t really need to know. They are just chained by a logical and:

    (Video) CSS :not( ) pseudo-class Selector

    If the tag is “body” and the class list does not include “home” and the class list does not include “away” and the class list does not include “page-50”, then …

    Of course using the not yet widely available level 4 selectors (body:not(.home, .away, .page-50) would be simpler:

    If the tag is “body” and the class list does not include any of “home”, “away” or “page-50”, then …

  6. Roger Poole

    Permalink to comment#

    Good grief, I hate to be the na sayer but Can I Use :not() sure kills any bright hopes for this. I fully expected IE11 to not support it (and I’ve got a bunch of those users) but even Edge, Chrome, and Firefox are not on board yet.

    This seems to be a Safari only selector…

    • Chris Coyier

      Permalink to comment#

      To be clear, you’re ONLY talking about the fancy comma-separated :not(a, b, c) style.

      Regular :not(a):not(b):not(c) style is supported everywhere.

    • Rodrigo

      Permalink to comment#

      The CSS3 selector :not() is widely supported (including IE9+).
      What is only supported by Saffari is the list argument, like :not(a, b, c).

    • Mike Dailey

      Permalink to comment#

      You gave me a damn heart attack! That’s only for the selector list argument of :not(), which is the :not(.a, .b, .c) thing. Just straight up :not(.a) is fine, as is :not(.a):not(.b):not(.c)

    • Jarryd

      (Video) CSS : Multiple classes inside :not()

      Permalink to comment#

      That’s only for a list of multiple selectors, the basic implementation of :not() works across most browsers.

    • rafi

      Permalink to comment#

      Being able to chain selectors within :not() is not fully supported but :not() itself is https://caniuse.com/#feat=mdn-css_selectors_not

  7. James Little

    Permalink to comment#

    I think you might be looking at selector list argument of :not(), which only works in Safari, yeah. But :not itself is part of the CSS3 selectors listing, which seems to be green across the board.

    So you can use :not() wherever, but we might have to hold off on using it with a list of selectors for now, like so:

    .headline:not(h1, h2, h3) { ... }
    • Mattia Astorino

      Permalink to comment#

      Selectors list inside the :not() selector is part of Selectors 4 Spec

  8. Mike

    Permalink to comment#

    :not() has been supported by all browsers for a long time. There is no reason not to use it.

  9. Jim S

    Permalink to comment#

    (Video) 10 CSS Pro Tips - Code this, NOT that!

    I could see how this could be powerful, but I’m a little hesitant to start using this. Doesn’t this have the same dangers as using !important because you’re overriding the cascade?

    On the front page of CSS-Tricks I see this done with some a tags successfully (the site looks dayung good.) But I’m not sure I want to override things like this where selectors (and properties) are being overridden with frequency:

    a:not(.button):not(.commentPreviewButton):not(.comment-reply-link):focus, a:not(.button):not(.commentPreviewButton):not(.comment-reply-link):hover {
    background: -webkit-gradient(linear,left top,right top,from(#ff8a00),to(#da1b60));
    background: linear-gradient(to right,#ff8a00,#da1b60);
    -webkit-background-clip: text;
    -webkit-text-fill-color: transparent;
    -webkit-box-decoration-break: clone;
    box-decoration-break: clone;
    text-shadow: none;

    I guess I’d have to see the code, maybe it’s much simpler in their codebase?

    • Chris Coyier

      Permalink to comment#

      I wasn’t even thinking of that particular code when writing this, but it makes a fairly good point. I don’t control the classes commentPreviewButton and comment-reply-link. They come from WordPress core or plugins. I could probably write filters to control them, but that’s technical debt at a level I’d rather not deal with. I’ll take my technical debt in a CSS selector, because of my personal skillset. That selector helps me to what I want to do, targeting most links, but avoiding a few specifically based on class name.

    • Jim S

      Permalink to comment#

      Yeah, I think I should take back in part what I said about !important- because it’s not an uncontrolled override. At least :not has you specify. The way it’s used here makes sense especially in environments where you don’t have control over some of the environment like WordPress like you said. But this probably is the exception more than the rule.

  10. J. Hogue

    Permalink to comment#

    I encountered someone’s code that did not understand this concept in the wild —worse, in the Production code of a well-known CMS’s admin. The code was like this:

    #some-id *, #some-id *:not(div),#some-id *:not(svg *) { stuff }

    …which is just insane. The first rule is not needed if the second rule is present. And the third rule just makes you wonder what this world is coming to.

    Please please be careful with the power that CSS gives you. Make sure you understand the rules before you apply them.

  11. Matthew Wilcox

    Permalink to comment#

    AND is chained. OR is achieved through new selectors:

    html:not('.foo'),html:not('.bar') { color: red;}
    (Video) How you can simplify your CSS with :is()

This comment thread is closed. If you have important information to share, please contact us.


1. Up your CSS game with these 3 pseudo-classes that nobody use
(Kevin Powell)
2. min(), max(), and clamp() are CSS magic!
(Kevin Powell)
3. pseudo-classes can do more than you might think
(Kevin Powell)
4. Learn CSS Pseudo Elements In 8 Minutes
(Web Dev Simplified)
5. Yet Another 5 Must Know CSS Tricks That Almost Nobody Knows
(Web Dev Simplified)
6. 3 More Life-Changing CSS Tips
Top Articles
Latest Posts
Article information

Author: Jamar Nader

Last Updated: 03/17/2023

Views: 6048

Rating: 4.4 / 5 (55 voted)

Reviews: 94% of readers found this page helpful

Author information

Name: Jamar Nader

Birthday: 1995-02-28

Address: Apt. 536 6162 Reichel Greens, Port Zackaryside, CT 22682-9804

Phone: +9958384818317

Job: IT Representative

Hobby: Scrapbooking, Hiking, Hunting, Kite flying, Blacksmithing, Video gaming, Foraging

Introduction: My name is Jamar Nader, I am a fine, shiny, colorful, bright, nice, perfect, curious person who loves writing and wants to share my knowledge and understanding with you.