Does the :not pseudo class increase the specificity of a selector?
Asked Answered
F

2

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>
Forgat answered 27/1, 2016 at 13:21 Comment(1)
Compare it to .blue.red instead, the .red still countsFestination
J
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.

Jacinda answered 27/1, 2016 at 13:31 Comment(14)
Curious , since stylesheets "cascade" why is background: red; not applied where it follows background: blue; declaration ?Upraise
@guest271314: Because the first rule is more specific. This is a question about specificity, after all.Jacinda
Can include description of 0,2,0 , 0,3,0 references at Answer ?Upraise
Good edit. It's really clear now how it works , thanks again!Forgat
@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 answerJacinda
@Jacinda 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 :jsfiddle.net/j8rfqf29Forgat
@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.Jacinda
@Jacinda Ugh I had a brainfart. Yes I meant :matches. I understand now thanks.Forgat
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.Detestable
@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). :not() does come in handy with type selectors, though - see #28300317Jacinda
@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.)Detestable
@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.Jacinda
@Ilmari Karonen: Oddly enough, a question just popped up with your exact use case - #35062756 Want to answer it, or may I in your place?Jacinda
@BoltClock: Answered. Thanks for the note!Detestable
C
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>
Clarify answered 27/1, 2016 at 13:23 Comment(3)
Oh I'm dumb. I guess I totally misread what they were saying. Thank you.Forgat
1) You need to use blockquote markup, see 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".Jacinda
Thanks @BoltClock. #1 -> Done. #2 -> Just kept the doc links, so I think the confusion is removed.Clarify

© 2022 - 2024 — McMap. All rights reserved.