UGURUS offers elite coaching and mentorship for agency owners looking to grow. Start with the free Agency Accelerator today.
The :not()
property in CSS is a negation pseudo class and accepts a simple selector or a selector list as an argument. It matches an element that is not represented by the argument. The passed argument may not contain additional selectors or any pseudo-element selectors.
The ability to use a list of selectors as an argument is considered experimental, although its supported is growing at the time of this writing, including Safari (since 2015), Firefox (since December 2020), and Chrome (since January 2021).
/* the X argument can be replaced with any simple selectors */
:not(X) {
property: value;
}
In this example we have an unordered list with a single class on the <li>
:
<ul>
<li></li>
<li class="different"></li>
<li></li>
</ul>
Our CSS would select all the <li>
elements except the one(s) with a class of .different
.
/* Style everything but the .different class */
li:not(.different) {
font-size: 3em;
}
You could also do the same using pseudo classes which are considered a simple selector.
p:not(:nth-child(2n+1)) {
font-size: 3em;
}
However, if we use a pseudo-element selector as our argument it will not produce the expected result.
:not(::first-line) { /* ::first-line is a pseudo element selector and not a simple selector */
color: white;
}
Complex selectors
These are newer than the basic :not()
selectors.
/* select all <p>s that are not descendants of <article> */
p:not(article *) {
}
This can get a little mind-bending with just a bit more nesting. For example:
h2:not(:where(article *, section *)) {
...
}
/*
<article>
<h2> No match! </h2>
</article>
<section>
<h2> No Match! </h2>
</section>
<aside>
<h2> Match! </h2>
</aside>
*/
Visual example
Specificity
The specificity of the :not
pseudo-class is the specificity of its argument. The :not()
pseudo-class does not add to the selector specificity, unlike other pseudo-classes.
Negations may not be nested so :not(:not(...))
is never permitted. Authors should also note that since pseudo-elements are not considered a simple selector, they are not valid as an argument to :not(X)
. Be mindful when using attribute selectors as some are not widely supported as others. Chaining :not
selectors with other :not
selectors is permissible.
Browser support
The :not()
pseudo class has been updated in the CSS Selectors Level 4 specification to allow an argument list. In CSS Selectors Level 3, it was only capable of accepting a single simple selector. As a result, browser support is a little divided between the Level 3 and Level 4 drafts.
Simple selectors
IE | Edge | Firefox | Chrome | Safari | Opera |
---|---|---|---|---|---|
9+ | All | All | All | 12.1+ | All |
Android Chrome | Android Firefox | Android Browser | iOS Safari | Opera Mobile |
---|---|---|---|---|
All | All | All | All | All |
Selector lists
This browser support data is from Caniuse, which has more detail. A number indicates that browser supports the feature at that version and up.
Desktop
Chrome | Firefox | IE | Edge | Safari |
---|---|---|---|---|
88 | 84 | No | 88 | 9 |
Mobile / Tablet
Android Chrome | Android Firefox | Android | iOS Safari |
---|---|---|---|
115 | 115 | 115 | 9.0-9.2 |
Thanks for covering the :not() selector, and as always with useful examples!
I would like to point out though, that the example depicted in the image of
p:not(:nth-child(2n+1))
is somewhat ambiguous and may be misleading, at least without explicit reference. The example holds true when looking at your demo page, where the first child of the<div class="f">
block is a<header>
element but anyone not looking at the demo page is likely going to expect that the second and fourth elements are selected/displayed with a white background — since the example selector really says: select any<p>
element that is not an odd child, whereas the image shows exactly the two odd elements as being selected.On the image “Visual representation of the varied uses of :not()” shouldn’t you point the 2 and 4 boxes ?
2n+1 is an odd number.So when you say :not(odd) should result in targeting the even numbers.
Am I wrong ?
Thanks for the wonderful article. However, I would like to know whether there is a way to identify a single element in my html page that would “not” take the general styling/css? What “not” does is specify all other element and “not” the one in the argument. I just want the opposite.
<style>
.div-class p{font-weight: bold;}
.div-class p:not(.no-style){font-weight: normal;}
</style>
<div class="div-class">
<p>This should be bold.</p>
<p class="no-style">This should not be bold.</p>
</div>
I would like the “p” with the “no-style” class to have a normal font weight. It’s currently the opposite. I hope to have made myself clear.
Thanks,
@Pratip: simply use straight forward css:
You don’t NOT want the paragraph with that class, but you do want the paragraph with the class no-style
A million years later, but you could just do
p:not(.no-style) { font-weight: bold }
it’s amazing, I’ve no idea how many times I am going to use it.
Regarding class selectors being valid “simple selectors” for a not…
are regex class selectors considered “simple”?
Can I create a selector (with whatever particular, correct syntax) like so…
Note that I’m asking because this specified rule is not working (fails SASS 3.3 compilation)
With as hard as css has always sucked at specifying a (pretty basic) rules engine, I’m thinking not…but considered it worth the shot to ask.
.foo:not([class*=bar]){}; can be used/ful too!
Just wanted to point out that
:not
can indeed be chained per the spec:html|*:not(:link):not(:visited)
§6.6.7 http://www.w3.org/TR/css3-selectors/#negation
I am using
should it work?
Yes, it works.
.foo:not(.bar, .baz, .qux)
doesn’t work in CSS.
You’re probably using SCSS/SASS that converts it into
.foo:not(.bar):not(.baz):not(.qux)
And my biggest problem with that, is the specificity it gains each time you add a :not
You right, Bernard Skibinski!
Use your example in simple search blog not DB.
Please forgive my english language.
Damn… this :not pseudo element was made backwards…
this…
li::before{content:”●”}
li::before:not(.menu-item){content:none}
is the same as…
li::before{content:”●”}
li.menu-item::before{content:none}
i thought this element was well made… an example below:
li::before, li::before:not(.menu-item) {content:”●”}
this should be the way :not() must work!
that last example says… that every li element will have {content:”●”} except .menu-item..
but we still have the same as i can see… i have tried tons ways but havent being able to make it work… please advice me if im wrong :)
This rule:
li::before, li::before:not(.menu-item) {content:”●”}
Is saying “Every li AND Every li that isn’t .menu-item should have content ●”.
I think you want this:
li::before:not(.menu-item) {content:”●”}
Thanks for your help, i appreciate that :) but like i said,
li::before:not(.menu-item) {content:”●”} (is the same as)
li::before(.menu-item) {content:none} (and this one is shorter)
i wanted to do like you said first:
“Every li AND Every li that isn’t .menu-item should have content ●”
but is not working for me…
Check out the “wrong uses” section here: http://callmenick.com/post/the-css-not-selector
The :not() selector will not work on pseudo elements like :before. Try writing it like this instead:
that was a good one i didn’t tried i think…
but didn’t work either, thanks anyway :)
and nice and simple article btw!
Hi How Are you .
I am fine thanks .
by by
Another useful one (especially when setting up defaults that you expect to be overridden by classes) is :not([class]). It only styles the element if it has no classes assigned to it at all. :)
Something I think is missed here is
What I recently learned is that you can actually get burned by this matter of “argument specificity inheritance”:
.foo:not(#bar)
will have a specificity of 0,1,1,0. Understood another way, you have now given a class the specificity of an ID.
It’s not too likely that someone might do this. However, a use-case I just ran into today was:
You wouldn’t expect this result at all. At least I didn’t. But it happened, because
:not()
inherits specificity. So I had a ruleset with a specificity of 0,0,2,0 overwriting a ruleset with a specificity of 0,0,1, 3.Here’s some documented proof of this in action:
The moral of the story is, “the argument you pass into
:not()
should be less specific than what it’s chained to.I’m using code that adds an icon to links that are external.
My Question is:
how do i alter this code so any link that is surrounding an < img >, will NOT show the external icon?
IE: < a >< img >< /a >
@ ryan
You can use this. This equates to – any a tag with an href attribute that ends in “.jpg”, “.gif”, “.png” Just add or remove whatever image file types you need.
How to apply :not in following situation
This should be bold.
This should be bold.
This should be bold.
This should not be bold.
I would like to set same background color using .menu class but at the same time I also dont want to apply same color to hidden-menu class
Thanks,
I wonder why:
.container > *:not(.someclass:first-child){ background:red }
isn’t working, while ..
.container > *:not(:first-child){ background:red }
works.
Tried just in FF, but this should work, shouldn’t it?
Try container > *:not(.some class):not(:first-child), you should have better luck chaining nots rather than chaining selectors inside a not
I think the “:not()” selector does add to specificity.
That’s from the MDN Page 2020.
That’s what’s reflected in the content as well. It’s not that the specificity is unchanged, but the specificity is determined by the highest specificity in its argument.
In case anyone struggles like I did, here is an example of chaining:
I was trying to do this:
I was not aware that comma separated :not selectors are invalid.
This should be added to the Specificity section of the article.
It is valid CSS. This has tripped me up before also, but you have to think like CSS does and read it as
:not(.someClass)
which technically allows.anotherClass
, and then further along reads:not(.anotherClass)
which allows.someClass
. By combining it in one line you are saying “not .someClass AND not .anotherClass”, not one OR the other (which basically cancels each other out).One point that I rarely see brought up as for
:not()
‘s usefulness is that you can keep the original styles of the element that you may not know the value of ahead of time. This comes in handy when you are applying utility classes to elements that could be of any display type.Basically, instead of this…
…we can instead hide the element when the parent is NOT hovered, and whenever it is, the rule below becomes invalid and the element it is attached to takes on its normal display value. Now your table won’t have
display:block
set to it like in the above example. I useddisplay:block
in this example because that seems to be the most common property when showing/hiding an element (none
andblock
).