97 comments

[ 3.7 ms ] story [ 114 ms ] thread
Interesting current versions of the following on windows fail

- Firefox - Chrome - Internet Explorer 9

Opera shows the expected result though.

I got a red box, chrome 21 on win 7.
Red box on Chrome 21 on Snow Leopard
I get a red box in everything but opera on linux. Seems to not be platform dependant at least.
I get a blue box on Opera for Windows.
red box on Safari 6.0 on OS X Mountain Lion
Seeing the same behavior on IE10 RTM as well.
Blue boxes on all of the following:

Opera 9.64 - FreeBSD 7.0

Opera 12.50 - Debian 6.0 & Windows 2008

Opera 11.64 - Debian 6.0 & Windows 2008

Opera 10.60 - Debian 6.0

Opera 10.63 - Windows 2008

Opera 9.8 - Windows 2008

MSIE 6.0 - Windows 2008

MSIE 5.5 - Windows 2008

So basically every Opera version and very old versions of MSIE.

(comment deleted)
For your sake, I hope this wasn't an actual bug you ran into :)
I guess the algorithm for specificity in all modern browsers involves a base-256 number. Why? I believe there are 4 slots for specificity - class, id, !important, and styles defined in the tag. 256^4 = 2^32, the size of an integer. Unfortunately we get this is as a side effect.
According to the CSS 2.1 spec, “Concatenating the four numbers a-b-c-d (in a number system with a large base) gives the specificity.” Base-256 is the obvious way to encode each digit efficiently, and I suppose all browsers that do this are still in compliance with the spec.
It still works with > 256 classes. I was expecting it to overflow and go back to blue when I added a 257th class.
If it is adding numbers, it may be losing the ID altogether.

  spec = classes + (id>>8) + (important>>16) + (styles>>24);
If the assumption was that classes would "probably" be under 256 and wasn't put in a char, it could be messing with the whole value.
Can you override an !important with 256 nested ids?
Nope, although I did find once you hit a certain number of ID's, it was something over 1000, not sure of exact number, it just ignores the rule altogether.
(comment deleted)
This seems to be taken from this answer on a question about HTML/CSS specificity

http://stackoverflow.com/a/11934505/950912

This is where this whole thing came from today. Somebody submitted this earlier, but it never got to the front page. I suggest a detailed readthrough of the question and all the answers for a great overview of how this works.
it's a feature not a bug. lol
Pretty awesome find. I imagine it will have some outrageous use some day for someone.
Or a way to alter the webpage when you get an XSS exploit..
There are easier ways that will work, so I can't see this being useful, only interesting.
Stranger, perhaps, this also works with the same class 256 times. That is <div class="c"> with a style def .c.c[...256...].c {}.

http://codepen.io/anon/pen/zbcxs

if you change it to #id#id it needs another 256 .c classes, interesting!
That is perplexing! Is there a stack of some sort in play here?
Interestingly, it doesn't seem like the classes need to be different for it to work, at least on Safari 6.0 if you change all the classes to .c000 it works just as well as having different ones.
An important side point: don't use #id unless you have a very very good reason and even then think twice. there is nothing more irritating than trying to refactor code that assumes and id input. This means you can't reuse that code to apply to multiple nodes at once. Same thing applies for both javascript and css.

I know it is semantically significant but in practice it is just hardly ever needed and frequently causes a royal pain in the ass.

BTW, performance is rarely a good reason either since by definition there is only one of anything that might be considered for an id so you can always find the element by class then save a reference to make repeated fast references.

I had the impression that class specificity (weight: 10) times 11 would weigh more than a single id (weight: 100), but I guess I'm wrong.
Weight 10 in a number system with a large enough base (e.g. webkit is using base 256).

I think the intent of the specification is that 1 id is always more specific than classes for any practical number of classes.

256 nested ids seems to create an overflow. If you remove the #i000 at the beginning of the rule on this: http://codepen.io/anon/pen/zefGg it turns red, but otherwise it stays blue.
Might depend on the browser, but Webkit-based browsers, for example, use a 0xffffff mask on the resulting specificity. And so...

  $ python
  >>> MASK = 0xffffff
  >>> MASK
  16777215
  >>> ID = 0x10000
  >>> ID * 256
  16777216
  >>> ID * 256 & MASK
  0
Are you sure this isn't a bug with Codepen.io?
It's very unlikely. I can't think of a scenario where it could be changing the CSS and/or HTML that still leaves it syntactically and semantically valid.
Not a bug, probably just CSS's ridiculous selector algorithm. IIRC, the algorithm looks something like (100xid's) + (10xclasses) ...
EDIT: i'm wrong
The algorithm looks like that "in a number system with a large base". It is arguably not what the spec intended but probably acceptable in exchange for performance.
It doesn't seem to work when you switch the order of the css selectors.
Both selectors have the same specificity, so the last one is applied. Add another class and the order won't matter.
(comment deleted)
Confused me for a second, but yeah your right.
[1] http://coding.smashingmagazine.com/2007/07/27/css-specificit...

This is a feature, not a bug. Its called CSS specificity.

Although, the link[1] seems to suggest it should be 100, not 256... that might be a bug.

Read the spec instead. It says "in a number system with a large base". I suspect the unspecific wording is on purpose (to allow optimisation for sane conditions), but it should be fairly clear that the intent is that classes cannot override ids.
"255 classes should be enough for everyone"?
Opera 12 displays a blue box while Chrome 21 and IE 9 show a red one. Another cross-browser incompatibility that we have to deal with...
Yay Opera!

Also, if you're really using >= 256 classes in your CSS you may have more systemic problems than just cross-brwoser compatibility.

What base does Opera use for specificity?
That's the sad thing about closed source software. Their implementation might be drastically different. I think they should write a blog post or at least a comment here about it though, I'm going to bug them now.
We use base 24, actually, but since we truncate before concatenating, we behave as expected here, unlike Gecko/WebKit. Obviously, a different TC that depends on one selector having more class names than another ("c" in CSS 2.1 6.4.3) will fail in Opera; it passes in GeckKit. See attachment at http://lists.w3.org/Archives/Public/www-style/2012Aug/0493.h... for an illustration.
(comment deleted)
Webkit source: http://trac.webkit.org/browser/trunk/Source/WebCore/css/CSSS...

Specifically:

  69	    case Id:
  70	        s += 0x10000;
  73	    case Class:
  88	            s += 0x100;
id selectors are worth (0x10000/0x100) == 0x100 == 256 class selectors.

This seems to be the mozilla source: http://hg.mozilla.org/mozilla-central/file/17c65d32c7b8/layo...

  521   nsAtomList* list = mIDList;
  522   while (nsnull != list) {
  523     weight += 0x010000;
  524     list = list->mNext;
  525   }
  526   list = mClassList;
  527   while (nsnull != list) {
  528     weight += 0x000100;
  529     list = list->mNext;
  530   }
Same weights, Id = 0x10000, Class = 0x100
Did they mean to fall through to case Class in line 73?
He elided some lines, there is a break.
(comment deleted)
For some reason, based on the w3 documentation, I was under the impression that an id had an order of magnitude more specificity than a class.

http://www.w3.org/TR/CSS2/cascade.html#specificity

I think it has _2_ (base 10) orders of magnitude more specificity. That's 10 times more specificity (than a single order)!
One might even say it has an order of magnitude more specificity than a single order.
From that spec:

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

So webkit is using 256 as "a large base".

I only just read this spec a few months ago. For years I was under the impression that the spec was "1 point for an element, 5 for a class, 10 for an id", and the selector with the highest point value won...

Actually, me too. Where does this misconception come from?
Under the same impression too, I definitely remember reading this on a W3C advice/info blog (dark brown background, white and blue header - useful memory).
Here's some of the specificity code from Webkit (right at the top of the file):

http://trac.webkit.org/browser/trunk/Source/WebCore/css/CSSS...

Basically, selectors are summed together with class selectors given a weight of 0x100, and id selectors given a weight of 0x10000, so this is a simple overflow. It's worth noting that a mask of 0xffffff is used, so using 256 #id's should give a specificity of zero.

In the example, switch the order of the rules and the background will switch -- last rule wins, all things being equal. Not surprising...

  $ python
  >>> CLASS = 0x100
  >>> ID = 0x10000
  >>> CLASS * 256 == ID
  True