How does the CSS specificity work?
The first says that any an item with class c
inside of any item with of class a
will be colored red.
.a .c {
color: red;
}
The second says that any an item with class c
inside of any item of class b
will be colored green. It takes precedence over the first rule as it is just as deep as the first rule, but defined after that rule.
.b .c {
color: green;
}
This says that any item with the class c
should be blue. But since it is not as descriptive as the rules above, it does not take precedence. If you have an item with class c
that is not nested inside a class a
or b
, then this rule will take effect.
.c {
color: blue;
}
So there are two rules to remember:
- The more specific rules get higher precedence
- The later defined rules get higher precedence than their just-as-specific counterparts.
CSS specificity and !important
Styles for a directly targeted element will always take precedence over inherited styles, regardless of the specificity of the inherited rule.
-- Specificity: Directly targeted elements vs. inherited styles
Note: the addition of the new contrived ruleset in Demo:
div.outer.outer.outer>div.inner1>div.inner2.inner2>aside.inner3 {
color: blue !important
}
It has an incredibly ridiculously unnecessarily huge specificity score of 0,0,7,4 and !important as well. CSS reads from right to left:
- Find an
<aside>
tag with the class of.inner3
- It must have a parent
<div>
that has the class of.inner2
. - Also that
<div class="inner2">
must have a parent<div>
with a class of.inner1
. - And it's imperative that
<div class="inner1">
have a parent<div>
with the class of.outer
.
All of these specific rules of the selector must be met just so a deeply nested <aside>
tag gets its style. Any descendant elements of .inner3
will inherit color: blue
property and value, but it is easily overridden by the likes of i.inner2
with color:red
.
<div class="inner3">
<p>This deeply nested text has <i class='inner2'>crazy specificity but this text is red.</i>
...
</p>
</div>
Note: the new ruleset at the bottom of CSS box:
div {
color: black !important
}
Now this selector is specific to all divs so here is how !important
has just been assigned a selector with a far reaching scope. This is probably more like the behavior you were expecting.
BTW, you probably noticed the duplicate classes:
.outer.outer.outer
That is called selector chaining which will increase a selector's specificity score. See Online Specificity Calculator.
Demo
div.outer.outer.outer>div.inner1>div.inner2.inner2>aside.inner3 { color: blue !important}
.outer .inner1 { color: green !important;}
.outer .inner1 .inner2 { color: red;}
div { color:black !important;}
<head> <link href="css/style.css" rel="stylesheet"> <link href="css/style1.css" rel="stylesheet"></head>
<body> <div class="outer"> <div class="inner1"> This text will be green... <div class="inner2"> <p>Voluptate labore cupidatat an enim quamquam ut anim malis, varias id sed veniam quibusdam, singulis aliqua ut singulis domesticarum, id aliqua illum o officia, et ab domesticarum, irure e excepteur o eram nam appellat coniunctione do commodo.. </p>
<aside class='inner3'> <p>This deeply nested text has <i class='inner1'>crazy specificity</i>, yet it only applies to it and its descendants with no specific <b class='inner2'>`color` property</b>.</p> </aside> </div> ...and this text will be green as well. </div> </div>
How are the points in CSS specificity calculated
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:
255 classes are not enough to override 1 id
...but 256 classes are enough to override 1 id
...and 256 tag-names are enough to override 1 class-name
...but, alas 256 ids are not enough to override 1 inline style (Updated 2012/8/15 -- you'll have to use
!important
)
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.
Update, March 2021:
Firefox no longer uses 256 as a base.
How does specificity work with inherited styles?
From the MDN page on Specifity
Styles for a directly targeted element will always take precedence over inherited styles, regardless of the specificity of the inherited rule.
https://developer.mozilla.org/en-US/docs/Web/CSS/Specificity
Hence p
will override .container
no matter what. The inherited style from .container
is overwritten
Understanding specificity: achieving desired selector outcomes without using !important
A class has a specificity of 10. An element has a specificity of 1.
Therefore, in the first instance:
- the
.main li a
selector has a specificity of 12. - the
.active a
selector has a specificity of 11
Because they both target the same element, and the former has a higher specificity, the latter loses the battle to style the element.
In the second instance:
- the
.primary p
selector has a specificity of 11. - the
.copyright
selector has a specificity of 10.
Again, because they both target the same element, and the former has a higher specificity, the latter loses the battle to style the element.
The !important
annotation trumps all specificity. Hence, with that applied, .active a
and .copyright
re-take the elements.
If you want to remove !important
, which would be the right thing to do as it's not necessary here, you can instead boost the specificity of the selectors.
An ID
has a specificity of 100. So that can quickly move a selector up in priority.
Here are some examples:
.main li a { color: #7ab2c1; } /* previous winner; specificity 12 */.main .active a { color: #ff0000; } /* added class selector; specificity now 21 */.primary p { font-size: 12px; } /* previous winner; specificity 11 */#copyright { font-size: 8px;} /* switched to ID selector; specificity now 100 */
<nav class="main"> <ul class="group"> <li class="active"><a href="#">Home</a></li> <li><a href="#">About</a></li> <li><a href="#">Contact</a></li> </ul></nav><footer class="primary"> <p><a href="#">Sign up</a> for our newsletter, it's a racket!</p> <p id="copyright">Copyright © Sven's Snowshoe Emporium. All Rights Reserved.</p></footer>
Relationship between !important and CSS specificity
Specificity in CSS only concerns selectors, not their associated declarations. !important
applies to a declaration, so it alone plays no role in specificity.
However, !important
influences the cascade, which is the overall calculation of styles for a certain element when more than one of the same property declaration applies to it. Or, as Christopher Altman succinctly describes:
!important
is a spades card. It trumps all specificity points.
But not only that: because it influences the cascade overall, if you have more than one !important
selector with a rule containing an !important
declaration matching the same element then selector specificity will continue to apply. Again, this is simply due to having more than one rule applying to the same element.
In other words, for two rules with unequal selectors in the same stylesheet (e.g. same user stylesheet, same internal author stylesheet, or same external author stylesheet), the rules with the most specific selector apply. If there are any !important
styles, the one in the rule with the most specific selector wins. Finally, since you can only have something that's either important or not, that's quite as far as you can go in influencing the cascade.
Here's an illustration of the various uses of !important
and how they're applied:
The
!important
declaration always overrides the one without it (except in IE6 and older):/* In a <style> element */
#id {
color: red !important;
color: blue;
}If there is more than one
!important
declaration in a rule with the same level of specificity, the later-declared one wins:/* In a <style> element */
#id {
color: red !important;
color: blue !important;
}If you declare the same rule and the same property in two different places,
!important
follows the cascading order if both declarations are important:/* In an externally-linked stylesheet */
#id {
color: red !important;
}
/* In a <style> element appearing after the external stylesheet */
#id {
color: blue !important; /* This one wins */
}For the following HTML:
<span id="id" class="class">Text</span>
If you have two different rules and one
!important
:#id {
color: red;
}
.class {
color: blue !important;
}That
!important
always wins.But when you have more than one
!important
:#id {
color: red !important;
}
.class {
color: blue !important;
}The
#id
rule has a more specific selector, so that one wins.
CSS specificity testing
The method I settled with is to use getComputedStyle to get the style with "highest priority". In the css I add a "tag" to the content property. In jasmine I then check if the desired tag is the computedStyle. (I will extend this in scss so that the content property is set by a mixin if test mode is used and not set in production.) This only makes a unit test for the class of highest priority, but not for the second highest etc.
Below is a tests to illustrate the example (only the first and last should pass).
// specs codedescribe("CSS", function() { it("Div element of class test should be handled by .test", () => { const testdiv = document.getElementById("testdiv") m = window.getComputedStyle(testdiv).getPropertyValue("content"); expect(m).toEqual('".test"'); });
it("Div element of class test should be handled by div", () => { const testdiv = document.getElementById("testdiv") m = window.getComputedStyle(testdiv).getPropertyValue("content"); expect(m).toEqual('"div"'); });
it("Div element should be handled by .test", () => { const testdiv = document.getElementById("testdiv2") m = window.getComputedStyle(testdiv).getPropertyValue("content"); expect(m).toEqual('".test"'); });
it("Div element of class test should be handled by div", () => { const testdiv = document.getElementById("testdiv2") m = window.getComputedStyle(testdiv).getPropertyValue("content"); expect(m).toEqual('"div"'); });
});
// load jasmine htmlReporter(function() { var env = jasmine.getEnv(); env.addReporter(new jasmine.HtmlReporter()); env.execute();}());
.test { content: '.test';}
div { content: 'div';}
<script src="https://cdn.jsdelivr.net/jasmine/1.3.1/jasmine.js"></script><script src="https://cdn.jsdelivr.net/jasmine/1.3.1/jasmine-html.js"></script><link href="https://cdn.jsdelivr.net/jasmine/1.3.1/jasmine.css" rel="stylesheet"/><div class="test" id="testdiv">TestDiv</div><div id="testdiv2">TestDiv</div>
How does CSS specificity decide which styles to apply?
It's based on IDs
, classes
and tags
. IDs
have the highest specificity, then classes
then tags
, so:
.item a == 0 1 1 0 (id) 1 (class=item) 1 (tag=a)
.special == 0 1 0
#foo == 1 0 0
#foo .bar a == 1 1 1
#foo #bar == 2 0 0
whichever has the most wins :) If it's a tie, whichever one comes last in the document wins. Note that 1 0 0
beats 0 1000 1000
If you want .special
to apply, make it more specific: .item a.special
Specificity rules for comma delineated lists
Remember that CSS is cascading - meaning the style that is referenced FURTHER down a CSS file will take precedence assuming the selector is the same:
header { background-color: red;}p, span, header { background-color: yellow;}
<header> HEADER</header>
Why does the :link pseudo class break expected CSS specificity rules?
The specification you link to states that a pseudo-class (:link
in this case) has higher specificity than an element name. To be precise, using the a-b-c-d format, your three selectors come out as:
a-b-c-d
0 0 1 1
0 0 0 3
0 0 1 3
Your confusion possible comes from your use of the term "pseudo selector" which fails to recognise the distinction between pseudo-classes such as :link
and pseudo-elements such as :first-line
.
Related Topics
How to Include View/Partial Specific Styling in Angularjs
Select All Child Elements Recursively in Css
Make the First Character Uppercase in Css
"Text-Align: Justify;" Inline-Block Elements Properly
What Does "I" Mean in a CSS Attribute Selector
Parent & Child With Position Fixed, Parent Overflow:Hidden Bug
How to Make the Items in the Last Row Consume Remaining Space in CSS Grid
Is the CSS :Not() Selector Supposed to Work With Distant Descendants
Scrolling a Flexbox With Overflowing Content
Twitter Bootstrap Multilevel Dropdown Menu
Css Background Opacity With Rgba Not Working in Ie 8
Repeat Table Headers in Print Mode
Is Background-Position-X (Background-Position-Y) a Standard W3C CSS Property