Why Is This 11 Class Selector Less Specific Than the Id

Why is this 11 class selector less specific than the ID?

Because the CSS specificity point system is exactly as you have specified:

  • Style attribute: 1,0,0,0
  • ID: 0,1,0,0
  • Class, pseudo-class, attribute selector: 0,0,1,0
  • Element: 0,0,0,1

Specificity

The commas are there to remind us that this isn't really a "base 10" system, in that you could technically have a specificity value of like 0,1,13,4 - and that "13" doesn't spill over like a base 10 system would.

Your ID selector is 0,1,0,0, and your combined class selector is 0,0,11,0.

At no point will any combination of class selectors ever override a single ID selectors, as is seen in the following:

#box {  width: 100px;  height: 100px;  background-color: #ff0; /* yellow */}
.one.two.three.four.five.six.seven.eight.nine.ten.eleven { background-color: #f00; /* red */}
<div id="box" class="one two three four five six seven eight nine ten eleven"></div>

Is an attribute selector for the ID attribute less specific than an ID selector?

An attribute selector will always be less specific than an ID selector; its specificity value does not change based on the attribute name. Selectors only maps specific attribute names to class selectors and ID selectors; an attribute selector is a generic concept and does not contain any such mappings.

The only way for a complex selector to have ID specificity is if it contains one or more ID selectors. Implementation limits aside, it is theoretically not possible to override even a single ID selector with any number of attribute selectors or any other type of simple selector.

Here is how your two selectors compare:

/* 1 attribute, 2 types -> specificity = 0-1-2 */
html div[id^="blue"] {
background-color: blue
}

/* 1 ID -> specificity = 1-0-0 */
#blue4 {
background-color: red
}

Even the addition of html doesn't help because it's just a type selector. Change it to :root and you get a pseudo-class which is equally specific to an attribute selector, and thus still less specific than an ID.

Why can't I beat an ID with multiple classes?

Simply put: an ID will always beat any number of classes, pseudo-classes, attribute selectors or type selectors, but not necessarily another ID. That's all you need to remember.

Or to get into the technical nitty gritty: specificity isn't counted in some decimal numeric base that we all use. IDs are not worth "100 points", classes/attributes/pseudo-classes are not "10 points", types/pseudo-elements are not "1 point", etc. You don't add these numbers up and compare them, mathematically, based on their sum; that's not how it works. (You do add up the individual number of IDs, number of classes/attributes/pseudo-classes, etc, but you don't add all the individual numbers up to a single total.)

The specificity of these simple selectors is counted in a rather different way. The spec says it best:

9. Calculating a selector's specificity


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 */

Notice that it says "concatenating" (as in joining strings together), not "adding" (as in the arithmetic sense of 2 + 2 = 4).

Notice also that it says "a number system with a large base"; this is just to illustrate that you don't take these specificity scores as decimal numbers, where 13 × 10 = 130 is greater than 1 × 100 = 100 in layman's terms.

This is how you would calculate the specificity of your selectors:

/* 1 ID, 1 class     -> specificity = 1-1-0 */
#big .little

/* 1 ID, 2 classes -> specificity = 1-2-0 */
#big .little.little

/* 0 IDs, 13 classes -> specificity = 0-13-0 */
.little.little.little.little.little.little.little.little.little.little.little.little.little

Notice now how the specificity of the third selector is less than the first two, because there are no ID selectors in use?

When comparing the other two selectors, both of which have an ID selector each, you'll see that the second selector has one more class. In this case, the second selector wins due to the extra class selector, even though each has an ID selector, because the ID selectors by themselves share equal specificity.

Why is the # selector of lesser specificity than anything?

I think the idea of "why" is more a "generational" or "authority" view point. If #Parent (of any generation back) says all my children who meet qualification "x" (in your case, span) are going to be given an inheritance of "y" (whatever css property), it doesn't matter what the single individual #Child wants, it needs the authority of the #Parent to get it if the parent has stated otherwise.

Added on edit: The inline style would then be the rebellious child, and the !important the crack down parent. Edit: I kept this for humor, but I don't think it reflects the idea as well as my later statement below.

Added on edit to question in comment: Given:

#outer span ...
#inner (which is a span element)

Then to help insure #inner selection I recommend:

body span#inner (*edit:* just span#inner works *edit:* if defined later)

or give body an id and

#bodyId #inner

Of course, these can still be overridden. The more "generations" involved, the more it becomes difficult to change the behavior because of the generational consensus (if great grandpa and grandpa and parent are all in agreement, it's likely the child is not going to get away with doing his own thing).

I had to majorly rewrite this section on later edit
Given this HTML:

<div id="grandparent">
<div id="parent">
<div id="child"></div>
</div>
</div>

I had previously stated that "#parent div has greater authority than #grandparent div. Both have generational authority, in fact, an 'equal' generational authority, but the first is 'nearer' generation" wins. The error in that is that "nearer" generationally is not what matters, but rather last to be granted authority. Given equal authority powers, the own designated last is the one that wins.

I believe I can still stand by this statement: With that thought in mind, a selector like #child[id] (which outweighs both previous selectors) treats its attributes as permissions for greater authority to rule that which itself controls. Having the # already gave it authority, but not enough to override a # of a earlier generation if that earlier generation also carries another selector granting more authority.

So #grandparent div outweighs #child but not div#child if it is last to receive authority [added this], and not #child[id] because the [id] adds greater authority for the #child to rule itself. If equal selectivity then last one to be granted authority wins.

Again, the style attribute setting a style property itself really acts more like a supreme granting of authority to rule oneself, assuming something more "!important" doesn't take it away.

As a summary statement to answer "why" it is this way (and not in line with "set" theory), I believe it is not about accuracy or really even specificity (though that is the term used) as indeed then one would expect #ChildsName to be the final unique say in the matter because nothing more specific need be said. Rather, however, while the documentation may not state it as such, "selectivity" is really structured on a granting of authority. Who has the most "rights" to rule the element, and given a "tie", who was the last one to be granted those rights.

How element selector is more specific than id selector?

To understand CSS specificity, read The Specificity Wars. There’s a handy reference sheet, too:

Sample Image

So, a selector like #foo would have 1,0,0 specificity, while an element selector like p would have 0,0,1 specificity. Out of these two, the ID selector would “win” as 100 is greater than 1.

A more specific (heh) version which also includes pseudo-elements and pseudo-classes can be found here: http://www.standardista.com/css3/css-specificity/

Sample Image

Why do 12 element selectors not override single class selector in CSS?

Does a single class selector always win over an arbitrary number of element selectors?

That's exactly it. Essentially, you have to think in a number system with an "arbitrarily large base". That is, 12 element selectors gives you a specificity that could be described as "0-0-0-12", which doesn't translate to "0-0-1-2", as the base of the number system is not 10.

And yes, this is one of the reasons people recommend avoiding ID selectors.

Here is a piece of relevant specification, although I don't really think their example does anything to help clarify this issue...

What is the difference between id selector and class selector when using border style

Without seeing the other CSS that might be involved, the likely answer is CSS specificity.

There are many guides to CSS specificity out there such as this one, but the general math for CSS specificity is:

  • element selectors such as div = 1
  • class selectors such as .edit-input = 10
  • id selectors such as #title = 100

Because #id is such a heavily-weighted selector, it's a good idea to avoid using ids as selectors in CSS as much as possible. They're much harder to override in subsequent styling.


If other styling in the page includes a rule such as this (for example):

div .edit-input { /* selector "weight": 11 */
border: 1px solid #DFE1E7;
}

Then this subsequent rule will have no effect, because it's less specific:

.edit-input { /* selector "weight": 10 */
border: 0;
}

You'll need to provide a selector that is at least as specific, if not more so. Perhaps something like this:

.el-input .edit-input { /* selector "weight": 20 */
border: 0;
}


To get this right, inspect the element using your browser's Web Inspector tools, and see what other CSS is getting applied. Then write your own CSS with enough specificity to override the existing default styling.

CSS specificity: Why isn't CSS specificity weight of 10 or more class selectors greater than 1 id selector?

The idea that you add the numbers to get the specificity is actually wrong. The results of the calculation are the same most of the time, but you have found the edge case where it differs.

From the W3C CSS2 specification:

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

If you follow the example in that page, you find that the specificities of the rules are as follows:

.a1 .a2 .a3 .a4 .a5 .a6 .a7 .a8 .a9 .a10 .a11 .a12 .a13    ||    0,0,13,0
#id1 || 0,1,0,0

Looking at the calculation this way, it is obvious that the ID selector wins. Indeed, one ID selector will override any number of class or element selectors. In turn, an inline definition will override ID style.

Prioritize id selector over an id and class

I suggest you to add another id selector to the first set of CSS rules.

 #cont #hello {
color:blue;
}

#cont .hello {
color:red;
}

DEMO http://jsfiddle.net/a_incarnati/53q74jah/

In this case the color was overridden in red because you were using just one id selector #hello and that it's less specific than a selector with 2 ids combined or one id and one class combined, like you have done:

#cont .hello {
color:blue;
}

One of the things to take into account when writing CSS code, it’s the concept of CSS specificity. Understanding well this concept will avoid you to have to use !important;

As Mozilla Developer Network defines it, specificity is nonetheless:

Specificity is the means by which a browser decides which property
values are the most relevant to an element and gets to be applied.
Specificity is only based on the matching rules which are composed of
selectors of different sorts.

The following list of selectors is by increasing specificity:

  • Universal selectors
  • Type selectors
  • Class selectors
  • Attributes selectors
  • Pseudo-classes
  • ID selectors
  • Inline style

You can measure specificity counting how many selectors are present in a CSS statement.

CSS Specificity can be represented by 4 columns of priority:

inline=1|0|0|0

id=0|1|0|0

class=0|0|1|0

element=0|0|0|1

Left to right, the highest number takes priority.

Sample Image



Related Topics



Leave a reply



Submit