

256 CSS Classes Can Override an #id - alpb
http://codepen.io/chriscoyier/pen/lzjqh

======
bingaling
Webkit source:
[http://trac.webkit.org/browser/trunk/Source/WebCore/css/CSSS...](http://trac.webkit.org/browser/trunk/Source/WebCore/css/CSSSelector.cpp?rev=81845#L63)

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...](http://hg.mozilla.org/mozilla-
central/file/17c65d32c7b8/layout/style/StyleRule.cpp#l521)

    
    
      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

~~~
dclowd9901
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>

~~~
bodhi
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...

~~~
Bootvis
Actually, me too. Where does this misconception come from?

~~~
RossM
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).

------
gburt
[1] [http://coding.smashingmagazine.com/2007/07/27/css-
specificit...](http://coding.smashingmagazine.com/2007/07/27/css-specificity-
things-you-should-know/)

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.

~~~
nemetroid
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.

~~~
lloeki
_"255 classes should be enough for everyone"_?

~~~
sageikosa
Seriously!

------
Cushman
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>

~~~
emp_
if you change it to #id#id it needs another 256 .c classes, interesting!

~~~
jlogsdon
That is perplexing! Is there a stack of some sort in play here?

------
prezjordan
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.

~~~
yonran
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.

~~~
mmahemoff
It still works with > 256 classes. I was expecting it to overflow and go back
to blue when I added a 257th class.

~~~
SoftwareMaven
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.

------
thezilch
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

------
zheng
This seems to be taken from this answer on a question about HTML/CSS
specificity

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

~~~
eykanal
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.

------
whichdan
For your sake, I hope this wasn't an actual bug you ran into :)

------
arrrg
Can someone explain the thinking behind this? Wouldn’t it be much simpler to
have #id always override a .class?

The 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.

~~~
Steuard
As far as I can tell from the specification posts here, it's entirely to make
implementation more feasible. Rather than some complicated calculation of
precedence, you can just assign each rule a single score. As long as the weird
exception essentially never comes up (which is the point of specifying "a
number system with a large base"), it's an efficient and sensible way to
implement the desired rule.

------
Osiris
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...

~~~
Foy
Yay Opera!

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

~~~
duaneb
What base does Opera use for specificity?

~~~
lastorset
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...](http://lists.w3.org/Archives/Public/www-
style/2012Aug/0493.html) for an illustration.

~~~
lastorset
Oops, should be base 25, obvs.

------
chimi
I suppose someone should update this question then, because it looks like to
me the limit is 255...

[http://stackoverflow.com/questions/4354921/css-is-there-a-
li...](http://stackoverflow.com/questions/4354921/css-is-there-a-limit-on-how-
many-classes-an-html-can-have)

~~~
badusername
I don't think the class limit is 255, it is still a fuzzy number as the post
declares. Here, I've modified the codepen to include another 256th class, and
the CSS declarations on that class are applied to the element.
<http://codepen.io/anon/pen/cKuBx>

------
sambenson
It's not a bug, OP found out about it from my question on Stack Overflow:
[http://stackoverflow.com/questions/2809024/points-in-css-
spe...](http://stackoverflow.com/questions/2809024/points-in-css-specificity)

------
dfischer
I recommend not using IDs due to selector specificity and the scenario where
you most likely will run into annoying #ID issues and think about using
`!important`.

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>

~~~
Steuard
I'm obviously lacking in imagination here. How would using an ID for styling a
"clearly one-per-page" element lead to problems? I'm thinking of things like
the main page title, or some sort of primary navigation block. The whole point
there is that I want the specific rules for those elements to override the
defaults, right?

~~~
dfischer
It may be "clearly one-per-page" now, but it may not be. You don't really gain
anything by using an ID. Keep the selector specificity simple so it doesn't
bite you in the ass and cause a refactor.

.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.

------
mey
Interesting current versions of the following on windows fail

\- Firefox \- Chrome \- Internet Explorer 9

Opera shows the expected result though.

~~~
revx
I got a red box, chrome 21 on win 7.

~~~
simcop2387
I get a red box in everything but opera on linux. Seems to not be platform
dependant at least.

~~~
jlarocco
I get a blue box on Opera for Windows.

------
sil3ntmac
Not a bug, probably just CSS's ridiculous selector algorithm. IIRC, the
algorithm looks something like (100xid's) + (10xclasses) ...

~~~
nemetroid
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.

------
xer0x
Awesome! I can't believe this is trending on HN. But that is very cool..

Now, how is this useful?

~~~
sil3ntmac
Knowing CSS's selector algorithm is useful as it helps rule out possibilities
for CSS override situations.

Edit: punctuation

------
croddin
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.

~~~
croddin
Here is a better example of ids overflowing:
<http://codepen.io/anon/pen/Khwon>

------
nemetroid
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...](http://trac.webkit.org/browser/trunk/Source/WebCore/css/CSSSelector.cpp?rev=121551)

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.

------
tracker1
I'm guessing that the implementation uses a 32-bit integer for calculating
rule strengths as they apply to a selection. With that in mind, 8 bits used
for each variable.. so it would make sense that 256 would overflow into the
next value. see: [http://www.webteacher.ws/2008/05/19/tip-calculate-the-
specif...](http://www.webteacher.ws/2008/05/19/tip-calculate-the-specificity-
of-css-selectors/)

------
solox3
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.

~~~
d4n3
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.

------
chacham15
<http://code.google.com/edu/submissions/html-css-javascript/>

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.

------
marksyzm
I just tried doing this with nested ids and it didn't work so perhaps this is
for classes only. Might be worth trying layers of HTML tags also - see
<http://pastebin.com/7BhQdNAn>

------
lubujackson
Pretty awesome find. I imagine it will have some outrageous use some day for
someone.

~~~
adamdecaf
Or a way to alter the webpage when you get an XSS exploit..

~~~
StavrosK
There are easier ways that will work, so I can't see this being useful, only
interesting.

------
troels
I'm surprised nobody linked to this yet?
[http://www.stuffandnonsense.co.uk/archives/images/specificit...](http://www.stuffandnonsense.co.uk/archives/images/specificitywars-05v2.jpg)

------
huxley
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.

------
tosbourn
Don't worry guys, crisis averted:

#id { background: blue ! important;}

~~~
electrotype
Add !important to the 256 classes too and they win.

------
monsterix
Oh nice! Bug at international level :-) Looks like it is some kind of stack
and overflow in play.

------
vigrant
It doesn't seem to work when you switch the order of the css selectors.

~~~
nemetroid
Both selectors have the same specificity, so the last one is applied. Add
another class and the order won't matter.

~~~
vigrant
Confused me for a second, but yeah your right.

------
gee_totes
Are you sure this isn't a bug with Codepen.io?

~~~
nicholaides
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.

------
victorNicollet
Nice one. That's a bug I guess.

------
mycodebreaks
does that happen on all browsers?

------
dayjah
obscure++

------
jnand
it's a feature not a bug. lol

