28

I have read on css tricks that :not should not add additional specificity. But it looks like it does?

https://css-tricks.com/almanac/selectors/n/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.

Or am I missing something?

.red:not(.blue) {
  background: blue;
}

.red {
  height: 100px;
  width: 100px;
  background: red;
}
<div class="red">
</div>
BoltClock
  • 700,868
  • 160
  • 1,392
  • 1,356
Paran0a
  • 3,359
  • 3
  • 23
  • 48

2 Answers2

33

Yes, it adds the specificity of its argument. Look at the first sentence:

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.

So the specificity of .red:not(.blue) is equal to that of .red.blue — 2 class selectors, or (0, 2, 0), making it more specific than .red on its own. What the second sentence means is that the :not() itself does not contribute the additional specificity of a pseudo-class to make it (0, 3, 0), like the :hover in .red.blue:hover does for example.

BoltClock
  • 700,868
  • 160
  • 1,392
  • 1,356
  • Curious , since stylesheets "cascade" why is `background: red;` not applied where it _follows_ `background: blue;` declaration ? – guest271314 Jan 27 '16 at 13:34
  • 4
    @guest271314: Because the first rule is more specific. This is a question about specificity, after all. – BoltClock Jan 27 '16 at 13:35
  • Can include description of `0,2,0` , `0,3,0` references at Answer ? – guest271314 Jan 27 '16 at 13:38
  • Good edit. It's really clear now how it works , thanks again! – Paran0a Jan 27 '16 at 13:39
  • 3
    @guest271314: I don't think it's really necessary to include a tutorial on calculating specificity in every answer on the topic. There are a number of resources online that will explain it better than I can in any individual answer – BoltClock Jan 27 '16 at 13:41
  • @BoltClock So what is the difference between :not and for example :has in terms of specificity? If I understood correctly only :not doesn't add any specificity by itself. Meaning any other pseudo selector should override :not cause it's stronger. In this demo it's not the case. DEMO :https://jsfiddle.net/j8rfqf29/ – Paran0a Jan 27 '16 at 13:54
  • @Paran0a: You probably meant :matches, not :has. The specificity of :not and :matches is calculated the same way - take the specificity of its most specific argument. So .red:not(.blue) and .red:matches(.orange) are equally specific. But note that :matches isn't implemented on any other browser besides Safari 9 yet, so your demo isn't going to work as you expect on other browsers. – BoltClock Jan 27 '16 at 13:59
  • @BoltClock Ugh I had a brainfart. Yes I meant :matches. I understand now thanks. – Paran0a Jan 27 '16 at 14:05
  • A trick I've found occasionally useful for artificially increasing the specificity of a selector is to append `:not(.nosuchclassname)` or `:not(#nosuchid)` to it. Yes, it's ugly, but it's still better than resorting to `!important`. – Ilmari Karonen Jan 27 '16 at 17:10
  • 1
    @Ilmari Karonen: You don't even have to do that always - you can also simply repeat whichever simple selector is already in use, e.g. `.red.red` or `#id#id` (though it appears [the latter is bugged in IE](http://stackoverflow.com/questions/25565928/idid-repeated-occurrences-of-the-same-simple-selector-should-increase-specif)). `:not()` does come in handy with type selectors, though - see http://stackoverflow.com/questions/28299817/can-type-selectors-be-repeated-to-increase-specificity – BoltClock Jan 27 '16 at 17:12
  • 1
    @BoltClock: That requires the selector to already have a class or ID in it. Actually, my original use case for this trick was making a style like `a[rel=nofollow] { color: green }` (specificity 0,1,1; injected by a user script) take precedence over, say, `a#someid { color: black }` (specificity 1,0,1; already present in site style sheet). Using `a[rel=nofollow]:not(#nosuchid)` (specificity 1,1,1) does the trick. (Of course, `!important` would've worked too... except that it turned out some of the existing styles I wanted to override were *already* using `!important`.) – Ilmari Karonen Jan 27 '16 at 17:27
  • @Ilmari Karonen: Ah. That's certainly a case for using `:not()`. You're much less likely to have an ID already in the selector than a class. – BoltClock Jan 27 '16 at 17:37
  • 1
    @Ilmari Karonen: Oddly enough, a question just popped up with your *exact* use case - http://stackoverflow.com/questions/35062256/how-to-override-css-rule-with-id-selector Want to answer it, or may I in your place? – BoltClock Jan 28 '16 at 13:41
  • @BoltClock: [Answered.](http://stackoverflow.com/a/35065825) Thanks for the note! – Ilmari Karonen Jan 28 '16 at 15:44
9

The :not selector don't have it's own specificity, however the selector inside :not() do have.

From MDN

Selector Types

The following list of selector types is by increasing specificity:

  1. Type selectors (e.g., h1) and pseudo-elements (e.g., :before).
  2. Class selectors (e.g., .example), attributes selectors (e.g., [type="radio"]) and pseudo-classes (e.g., :hover).
  3. ID selectors (e.g., #example).

Universal selector (*), combinators (+, >, ~, ' ') and negation pseudo-class (:not()) have no effect on specificity. (The selectors declared inside :not() do, however.)


As you're having the rule .red:not(.blue) and the element <div class="red"> don't have the class blue, the rule is applied.

.red:not(.blue) {
  background: blue;
}

.red {
  height: 100px;
  width: 100px;
  background: red;
}
div {
  background: green;
  width: 50px;
  height: 50px;
  margin: 10px;
}
<div></div>
<div class="red"></div>
<div class="blue"></div>
Tushar
  • 85,780
  • 21
  • 159
  • 179
  • Oh I'm dumb. I guess I totally misread what they were saying. Thank you. – Paran0a Jan 27 '16 at 13:25
  • 4
    1) You need to use blockquote markup, see http://stackoverflow.com/help/referencing 2) This doesn't really address the :not(). If anything, it reinforces the OP's confusion by restating that "the negation pseudo-class [has] no effect on specificity". – BoltClock Jan 27 '16 at 13:32
  • Thanks @BoltClock. #1 -> Done. #2 -> Just kept the doc links, so I think the confusion is removed. – Tushar Jan 27 '16 at 13:35