The :not(X) property in CSS is a negation pseudo class and accepts a simple selector1 as an argument. Essentially, just another selector of any kind.

:not matches an element that is not represented by the argument. The passed argument may not contain additional selectors or any pseudo-element selectors.

See the Pen :not(X) by GRAY GHOST (@grayghostvisuals) on CodePen.

/* 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:

  <li class="different"></li>

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;

Visual representation of the varied uses of :not()

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.

Other Resources

Browser Support

Chrome Safari Firefox Opera IE Android iOS
14+ 4.0+ 3+ 11.1+ 9+ 2.1+ 3.0+

1 A simple selector is classified as a Type Selector, Universal Selector, Attribute Selector, Class Selector, ID Selector, or Pseudo Class Selector.


  1. mesamorpho
    Permalink to comment#

    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.

  2. razvan
    Permalink to comment#

    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 ?

  3. Pratip Ghosh
    Permalink to comment#

    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.

    .div-class p{font-weight: bold;}
    .div-class p:not(.no-style){font-weight: normal;}

    <div class="div-class">
    <p>This should be bold.</p>
    <p class="no-style">This should not be bold.</p>

    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.


    • alpipego
      Permalink to comment#

      @Pratip: simply use straight forward css:

      p {
          font-weight: bold;
      .no-style {
          font-weight: normal;

      You don’t NOT want the paragraph with that class, but you do want the paragraph with the class no-style

    • Tiffany Stoik
      Permalink to comment#

      A million years later, but you could just do

      p:not(.no-style) { font-weight: bold }

  4. Jimba Tamang

    it’s amazing, I’ve no idea how many times I am going to use it.

  5. K. Alan Bates
    Permalink to comment#

    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…

    [class *= "foo"] not([class *= "bar"]){
       /*This element is guaranteed to be foo and guaranteed to not be bar */
       content: "Do stuff";

    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.

  6. David Puerto
    Permalink to comment#

    .foo:not([class*=bar]){}; can be used/ful too!

  7. James Holby
    Permalink to comment#

    Just wanted to point out that :not can indeed be chained per the spec:


    §6.6.7 http://www.w3.org/TR/css3-selectors/#negation

  8. Lucas Martins
    Permalink to comment#

    I am using

    .foo:not(.bar, .baz, .qux)
  9. cridavcor
    Permalink to comment#

    Use your example in simple search blog not DB.

    Please forgive my english language.

  10. Luis Trinidad
    Permalink to comment#

    Damn… this :not pseudo element was made backwards…



    is the same as…


    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 :)

    • Joe
      Permalink to comment#

      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:”●”}

  11. Luis Trinidad
    Permalink to comment#

    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…

  12. Kick
    Permalink to comment#

    Hi How Are you .
    I am fine thanks .

    by by

  13. Corry Frydlewicz

    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. :)

  14. Paceaux
    Permalink to comment#

    Something I think is missed here is

    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.

    What I recently learned is that you can actually get burned by this matter of “argument specificity inheritance”:


    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:

         <section class="menu">
        <a href="/" class="icon-logo">
        [class*="icon-"]:not(.icon-wrapper) {
          line-height: 1;
        .menu ul > li a {
         line-height: 50px; //overwritten by the ruleset above

    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.

  15. Ryan
    Permalink to comment#

    I’m using code that adds an icon to links that are external.

    #block-system-main a[href^="http"], #block-system-main a[href^="https"] {
        background-image: url("/sites/default/files/external.png");
        background-repeat: no-repeat;
        background-position: right center;
        padding-right: 20px;

    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 >

Leave a Comment

Posting Code

We highly encourage you to post problematic HTML/CSS/JavaScript over on CodePen and include the link in your post. It's much easier to see, understand, and help with when you do that.

Markdown is supported, so you can write inline code like `<div>this</div>` or multiline blocks of code in triple backtick fences like this:

  function example() {
    element.innerHTML = "<div>code</div>";

We have a pretty good* newsletter.