15

Which selector is stronger?

#nav li.current

or

div #nav li

and second

a.test

or

.test .test

What is the answer?

random
  • 9,774
  • 10
  • 66
  • 83
jcubic
  • 61,973
  • 54
  • 229
  • 402
  • 13
    The first is `1,1,1` whereas the second is `1,0,2`, so the first is stronger. In the second part, you have `1,1` vs. `2,0`, making the second one stronger. – Niet the Dark Absol Oct 01 '13 at 13:42
  • 3
    A better question to ask is how to determine selector strength, then you can calculate it on your own. – Wesley Murch Oct 01 '13 at 13:42
  • 3
    Try it for yourself using the Specificity Calculator http://specificity.keegan.st/ – pwdst Oct 01 '13 at 13:42
  • 5
    @Kolink what are those ones, twos and zero and how to calculate them? – jcubic Oct 01 '13 at 13:43
  • 1
    IDs, classes, tags. That is the order of specificity. If a selector has more IDs, it wins. If they have the same, check the number of classes. If they have the same too, check the number of tags. – Niet the Dark Absol Oct 01 '13 at 13:45
  • For a more detailed understanding than can be easily given here you may find http://css-tricks.com/specifics-on-css-specificity/ helpful. – pwdst Oct 01 '13 at 13:46
  • 1
    CSS Specificity Wars http://www.stuffandnonsense.co.uk/archives/css_specificity_wars.html – biziclop Oct 01 '13 at 13:50
  • 3
    Ironically these are all poor selectors that professionals would avoid. – Wesley Murch Oct 01 '13 at 13:51
  • 1
    The question has already been answered, but I question the usefulness of these questions. There is never a reason to use `div #nav li`; just use `#nav li`. Also, `nav` is a tag now, so the use of `#nav` is questionable at best. If you find yourself needing `#nav li.current`, your html is probably poorly written, you'd be more likely to just use `#nav .current`. –  Oct 01 '13 at 14:00
  • 1
    @Llepwryd there's nothing wrong with naming an ID "nav". After all, that may be a `nav` element anyway. ``. Equally, the "current" class may apply to elements of different types. The `li` selector would specifically select `li` elements with that class. – James Donnelly Oct 01 '13 at 14:03
  • @Llepwryd A page can have multiple `nav` elements. – Wesley Murch Oct 01 '13 at 14:08
  • @JamesDonnelly I realize that you can use the id `#nav` with no problems, but it seems like bad practice. I wouldn't advise using ids like `#div` or `#ul` either. –  Oct 01 '13 at 14:13

2 Answers2

36

From the spec:

A selector's specificity is calculated as follows:

  • count the number of ID selectors in the selector (= a)
  • count the number of class selectors, attributes selectors, and pseudo-classes in the selector (= b)
  • count the number of type selectors and pseudo-elements in the selector (= c)
  • ignore the universal selector

Selectors inside the negation pseudo-class are counted like any other, but the negation itself does not count as a pseudo-class.

Concatenating the three numbers a-b-c (in a number system with a large base) gives the specificity.

Examples:

*               /* a=0 b=0 c=0 -> specificity =   0 */
LI              /* a=0 b=0 c=1 -> specificity =   1 */
UL LI           /* a=0 b=0 c=2 -> specificity =   2 */
UL OL+LI        /* a=0 b=0 c=3 -> specificity =   3 */
H1 + *[REL=up]  /* a=0 b=1 c=1 -> specificity =  11 */
UL OL LI.red    /* a=0 b=1 c=3 -> specificity =  13 */
LI.red.level    /* a=0 b=2 c=1 -> specificity =  21 */
#x34y           /* a=1 b=0 c=0 -> specificity = 100 */
#s12:not(FOO)   /* a=1 b=0 c=1 -> specificity = 101 */
BoltClock
  • 700,868
  • 160
  • 1,392
  • 1,356
user247702
  • 23,641
  • 15
  • 110
  • 157
  • 3
    Although this does not directly answer the OP's question, it provides all the tools needed for them to understand and answer themselves. Upvoted. – pwdst Oct 01 '13 at 13:48
  • 8
    @pwdst I would say that that is better than directly answering the question – Bill Oct 01 '13 at 13:48
  • 3
    @pwdst Teach a man to fish... – James Donnelly Oct 01 '13 at 13:52
  • 1
    @BillyMathews As it happens I agree completely, I was not criticising the answer in any way, simply saying that I thought this was the right approach to take. I thought that was clear in the comment, sorry if that was not the case. – pwdst Oct 01 '13 at 14:42
  • @pwdst Ahhh, I see. I think it was the 'although' that threw me off. – Bill Oct 01 '13 at 14:55
10

You can follow the following rules to calculate selectors as points.

A tag selector is worth 1 point.

A class selector is worth 10 points.

An ID selector is worth 100 points.

An inline style is worth 1,000 points.

#nav li.current = 100 + 1+10 = 111

div #nav li = 1 + 100 + 1 = 102

a.test = 1+10 = 11

.test .test = 10+10 = 20

Community
  • 1
  • 1
lvarayut
  • 13,963
  • 17
  • 63
  • 87
  • 1
    Does it mean that you can overwrite inline style using `#foo #bar #baz #quux #foo2 #bar2 #baz2 #quux2 #foo3 #bar3 #baz3`? – jcubic Oct 01 '13 at 13:56
  • It doesn't work http://jsfiddle.net/QNztu/. Inline style is not overwritten. – jcubic Oct 01 '13 at 14:04
  • @jcubic AFAIK, css selection works from right to left. so if the first selection is ID then it will **not** look for the next selection because ID's are meant to be unique. So, the points for your above css selectors is just `100`. – Mr_Green Oct 01 '13 at 14:15
  • @Mr_Green what about `#foo + #bar + #baz + #quux + #foo2 + #bar2 + #baz2 + #quux2 + #foo3 + #bar3 + #baz3` will it act the same? http://jsfiddle.net/QNztu/1/ – jcubic Oct 01 '13 at 14:28
  • @jcubic makes no sense. because **ID's are unique** it will make sense if you use tag names or class names instead of id's.. – Mr_Green Oct 01 '13 at 14:29
  • How much is `!important` worth? – Mike G Oct 01 '13 at 14:55
  • 3
    The syntax of powers of 10 is essentially incorrect. You can never override a higher priority selector with many lower priority selector, even with > 10 of them - as jcubic just discovered. Other posters have used a comma-separated priority order, `a,b,c,d` or `0,1,0,2`, which makes this more clear. – Patrick M Oct 01 '13 at 15:09
  • @Mr_Green I put 102 nested classes into one selector and it don't overwrite the inline style http://jsfiddle.net/QNztu/3/ – jcubic Oct 01 '13 at 16:20
  • @Mr_Green: Specificity doesn't care how unique your IDs are. If you have 10 ids in a selector then the specificity is 10 ids. – BoltClock Oct 01 '13 at 17:51
  • @Patrick M: I seriously need to work on an answer to [this question](http://stackoverflow.com/questions/2809024/points-in-css-specificity). – BoltClock Oct 01 '13 at 17:52
  • @mikeTheLiar: See http://stackoverflow.com/questions/5805040/important-in-css-specificity-points/5805204#5805204 although if you need to count `!important` in terms of precedence then it's 1 level more than an inline style, I guess? i.e. `!important` > inline style > id. – BoltClock Oct 01 '13 at 17:53
  • @BoltClock Wow, [Faust's answer](http://stackoverflow.com/a/11934505/1146608) there is awesome, and really on par to what jcubic is getting at here. I would have guessed that all browsers used a base-infinity system. I disagree with the on-hold/off topic the question is now classified under - I would go along with closed/dupe. – Patrick M Oct 01 '13 at 20:02
  • @Patrick M: His answer, while completely correct, still implies that adding up points makes sense as a system for counting specificity, just with a strange base, which will likely lead to even further misconception especially among CSS authors. Granted, the spec says to implement it as a system with an arbitrarily large base, but of course, unless you implemented specificity in some complex data type you won't really be able to count in an infinitely large base. – BoltClock Oct 02 '13 at 09:16
  • @Patrick M: I guess what I intend to get at is there are much simpler, clearer, and most importantly more foolproof ways to count specificity, such as what you've mentioned earlier, than to rely on an implementation detail. (And I really should be putting all this in my answer.) – BoltClock Oct 02 '13 at 09:22