256 CSS Classes Can Override an #id
codepen.io
codepen.io
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> 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...
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.
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. $ python
>>> CLASS = 0x100
>>> ID = 0x10000
>>> CLASS * 256 == ID
TrueThe way it is set up currently that’s basically always the case (since 256 .classes are rarely used), but there is this weird edge case when as many .classes are used.
I don’t think it’s possible to meaningfully work with a rule like that. It just seems so non-sensical.
Also, if you're really using >= 256 classes in your CSS you may have more systemic problems than just cross-brwoser compatibility.
and from irc: "in other words, its the size of the storage which matters and not really the base, other browsers seem to use 8 bits, we use 16" @shwetank
http://stackoverflow.com/questions/4354921/css-is-there-a-li...
I don't think it's absolute blasphemy to use #ids, but try to never use them. Think of it that way. I tend to use them only for #js-functionality hooks, which is also a good-practice to tell someone "don't freaking change this ID or you break the JS."
Tips from http://www.betterfrontend.com
.page-wrapper .page-main %article.main
There's no difference using that to
#page-wrapper #page-main %article#main
Psuedo example, those can be mix and matched with classes and IDS but doing so just complicates the selectors and the cascade.
There is of course exceptions and things that may just make total sense, but overall, it leads to complications. You don't gain any real benefits unless it's a JS hook for #id selector performance.
That's not very nice.
[0]: https://github.com/markdotto/github-buttons/blob/master/READ...
Thanks for the heads up. It should be fixed now. Clear cache the "hard" way if you have to.
- Firefox - Chrome - Internet Explorer 9
Opera shows the expected result though.
Now, how is this useful?
Edit: punctuation
$ python
>>> MASK = 0xffffff
>>> MASK
16777215
>>> ID = 0x10000
>>> ID * 256
16777216
>>> ID * 256 & MASK
0http://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.
I think the intent of the specification is that 1 id is always more specific than classes for any practical number of classes.
Look at the css section. id's, classes, and selectors have weights which are used to determine which rule wins in the event of a conflict.
#id { background: blue ! important;}