Points in CSS specificity

2018-12-31 02:49发布

Researching specificity I stumbled upon this blog - http://www.htmldog.com/guides/cssadvanced/specificity/

It states that specificity is a point-scoring system for CSS. It tells us that elements are worth 1 point, classes are worth 10 points and IDs are worth 100 points. It also goes on top say that these points are totaled and the overall amount is that selector's specificity.

For example:

body = 1 point
body .wrapper = 11 points
body .wrapper #container = 111 points

So, using these points surely the following CSS and HTML will result in the text being blue:

CSS:

#a {
    color: red;
}

.a .b .c .d .e .f .g .h .i .j .k .l .m .n .o {
  color: blue;
}

HTML:

<div class="a">
  <div class="b">
    <div class="c">
      <div class="d">
        <div class="e">
          <div class="f">
            <div class="g">
              <div class="h">
                <div class="i">
                  <div class="j">
                    <div class="k">
                      <div class="l">
                        <div class="m">
                          <div class="n">
                            <div class="o" id="a">
                              This should be blue.
                            </div>
                          </div>
                        </div>
                      </div>
                    </div>
                  </div>
                </div>
              </div>
            </div>
          </div>
        </div>
      </div>
    </div>
  </div>
</div>

RESULT:

http://jsfiddle.net/hkqCF/

Why is the text red when 15 classes would equal 150 points compared to 1 ID which equals 100 points?

EDIT:

So apparently the points aren’t just totalled, they’re concatenated. Read more about that here - http://www.stuffandnonsense.co.uk/archives/css_specificity_wars.html BUT, does that mean that the classes in our selector = 0,0,15,0 OR0,1,5,0?

My instincts tell me it’s the former as we KNOW the ID selector’s specificity looks like this: 0,1,0,0

7条回答
时光乱了年华
2楼-- · 2018-12-31 03:24

I don't believe that the blog's explanation is correct. The specification is here:

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

"Points" from a class selector can't add up to be more important than an "id" selector. It just doesn't work like that.

查看更多
余欢
3楼-- · 2018-12-31 03:26

I am currently using the book CSS Mastery: Advanced Web Standards Solutions.

Chapter 1, page 16 says:

To calculate how specific a rule is, each type of selector is assigned a numeric value. The specificity of a rule is then calculated by adding up the value of each of its selectors. Unfortunately, specificity is not calculated in base 10 but a high, unspecified, base number. This is to ensure that a highly specific selector, such as an ID selector, is never overridden by lots of less specific selectors, such as type selectors.

(emphasis mine) and

The specificity of a selector is broken down into four constituent levels: a, b, c, and d.

  • if the style is an inline style, then a = 1
  • b = the total number of id selectors
  • c = the number of class, pseudo-class, and attribute selectors
  • d = the number of type selectors and pseudo-element selectors

It goes on to say that you can often do the calculation in base-10, but only if all columns have values less than 10.


In your examples, ids are not worth 100 points; each is worth [0, 1, 0, 0] points. Therefore, one id beats 15 classes because [0, 1, 0, 0] is greater than [0, 0, 15, 0] in a high-base number system.

查看更多
长期被迫恋爱
4楼-- · 2018-12-31 03:29

Pekka's answer is practically correct, and probably the best way to think about the issue.

However, as many have already pointed out, the W3C CSS recommendation states that "Concatenating the three numbers a-b-c (in a number system with a large base) gives the specificity." So the geek in me just had to figure out just how large this base is.

It turns out that the "very large base" employed (at least by the 4 most commonly-used browsers*) to implement this standard algorithm is 256 or 28.

What this means is that a style specified with 0 ids and 256 class-names will over-ride a style specified with just 1 id. I tested this out with some fiddles:

So there is, effectively, a "point system," but it's not base 10. It's base 256. Here's how it works:

(28)2 or 65536, times the number of ids in the selector
+ (28)1 or 256, times the number of class-names in the selector
+ (28)0 or 1, times the number of tag-names in the selector

This isn't very practical for back-of-the-envelop exercises to communicate the concept.
That's probably why articles on the topic have been using base 10.

***** [Opera uses 216 (see karlcow’s comment). Some other selector engines use infinity — effectively no points system (see Simon Sapin’s comment).]

Update, July 2014:
As Blazemonger pointed out earlier in the year, webkit browsers (chrome, safari) now appear to use a higher base than 256. Perhaps 216, like Opera? IE and Firefox still use 256.

查看更多
倾城一夜雪
5楼-- · 2018-12-31 03:30

Good question.

I can't tell for sure - all the articles I manage to find avoid the example of multiple classes, e.g. here - but I assume that when it comes to comparing the specifity between a class selector and an ID, the class gets calculated with a value of 15 only, no matter how detailed it is.

That matches my experience in how specificity behaves.

However, there must be some stacking of classes because

.a .b .c .d .e .f .g .h .i .j .k .l .m .n .o

is more specific than

.o

the only explanation I have is that the specificity of stacked classes is calculated only against each other but not against IDs.

Update: I half-way get it now. It is not a points system, and the information about classes weighing 15 points is incorrect. It is a 4-part numbering system very well explained here.

The starting point is 4 figures:

style  id   class element
0,     0,   0,    0

According to the W3C explanation on specificity, the specificty values for the abovementioned rules are:

#a            0,1,0,0    = 100
classes       0,0,15,0   = ... see the comments

this is a numbering system with a very large (undefined?) base.

My understanding is that because the base is very large, no number in column 4 can beat a number > 0 in column 3, the same for column 2, column 1 .... Is this correct?

I'd be interested whether somebody with a better grasp at Math than me could explain th numbering system and how to convert it to decimal when the individual elements are larger than 9.

查看更多
临风纵饮
6楼-- · 2018-12-31 03:34

I am fond of comparison of Specificity ranking to Olympic Games medal table (gold first method — based first on the number of gold medals, then silver and then bronze).

It works also with your question (huge number of selectors in one specificity group). Specificity considered each group separately. In real world I've very rarely seen case with more than a dozen selectors).

There is also quite good specificity calculator available here. You can put your example (#a and .a .b .c .d .e .f .g .h .i .j .k .l .m .n .o) there and see the results.

Example of Rio 2016 Olympic Games medal table looks like enter image description here

查看更多
梦该遗忘
7楼-- · 2018-12-31 03:36

I would say that:

Element < Class < ID

I think they only stack into depending what you get if it is multiple of the same. So a Class will always overide the element and ID always over the Class but if it is down to which of 4 elements where 3 is to blue and 1 is to red it will be blue.

For Example:

.a .b .c .d .e .f .g .h .i .j .k .l
{
color: red;
}

 .m .n .o
{
color blue;
}

Should turn out red.

See Example http://jsfiddle.net/RWFWq/

"if 5things say red and 3 say blue well Ima go red"

查看更多
登录 后发表回答