Css not two class
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.
Try it
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.
Description
There are several unusual effects and outcomes when using :not() that you should keep in mind when using it:
- Useless selectors can be written using this pseudo-class. For example, :not(*) matches any element which is not an element, which is obviously nonsense, so the accompanying rule will never be applied.
- This pseudo-class can increase the specificity of a rule. For example, #foo:not(#bar) will match the same element as the simpler #foo , but has the higher specificity of two id selectors.
- The specificity of the :not() pseudo-class is replaced by the specificity of the most specific selector in its comma-separated argument of selectors; providing the same specificity as if it had been written :not(:is(argument)) .
- :not(.foo) will match anything that isn’t .foo , including and .
- This selector will match everything that is «not an X». This may be surprising when used with descendant combinators, since there are multiple paths to select a target element. For instance, body :not(table) a will still apply to links inside a , since , , , , , etc. can all match the :not(table) part of the selector.
- You can negate several selectors at the same time. Example: :not(.foo, .bar) is equivalent to :not(.foo):not(.bar) .
- If any selector passed to the :not() pseudo-class is invalid or not supported by the browser, the whole rule will be invalidated. The effective way to overcome this behavior is to use :is() pseudo-class, which accepts a forgiving selector list. For example :not(.foo, :invalid-pseudo-class) will invalidate a whole rule, but :not(:is(.foo, :invalid-pseudo-class)) will match any (including and ) element that isn’t .foo .
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 h2span> span class="bar">bar inside h2span> h2>
CSS
.fancy text-shadow: 2px 2px 3px gold; > /* elements that don't have a class `.fancy` */
p:not(.fancy) color: green; > /* Elements that are not elements */
body :not(p) text-decoration: underline; > /* Elements that are not s or `.fancy` */ body :not(div):not(.fancy) font-weight: bold; > /* Elements that are not s or `.fancy` */ body :not(div, .fancy) text-decoration: overline underline; > /* Elements inside an that aren't a with a class of `.foo` */ h2 :not(span.foo) color: red; >
Result
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 .foop> p class="bar">I am a paragraph with .barp> div>I am a div without a classdiv> div class="foo">I am a div with .foodiv> div class="bar">I am a div with .bardiv> div class="foo bar">I am a div with .foo and .bardiv>
CSS
/* Invalid rule, does nothing */ p:not(.foo, :invalid-pseudo-class) color: red; font-style: italic; > /* Select allelements without the `foo` class */
p:not(:is(.foo, :invalid-pseudo-class)) color: green; border-top: dotted thin currentcolor; > /* Select all elements without the `foo` or the `bar` class */ div:not(.foo, .bar) color: red; font-style: italic; > /* Select all 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.
Specifications
Browser compatibility
BCD tables only load in the browser
See also
Found a content problem with this page?
This page was last modified on Jul 18, 2023 by MDN contributors.
Your blueprint for a better internet.
CSS :not() with Multiple Classes
Say you want to select an element when it doesn’t have a certain class. That’s what the :not() selector is for.
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.
Comments
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!
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!
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)
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?).=>
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:
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…
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.
The CSS3 selector :not() is widely supported (including IE9+).
What is only supported by Saffari is the list argument, like :not(a, b, c).
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)
That’s only for a list of multiple selectors, the basic implementation of :not() works across most browsers.
Being able to chain selectors within :not() is not fully supported but :not() itself is https://caniuse.com/#feat=mdn-css_selectors_not
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:
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?
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.
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.
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 *)
…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.