Apart from Floats, the CSS Specificity is one of the most difficult concepts to grasp in Cascading Stylesheets. The different weight of selectors is usually the reason why your CSS-rules don’t apply to some elements, although you think they should have. In order to minimize the time for bug hunting you need to understand, how browsers interpret your code. And to understand that, you need to have a firm understanding on how specificity works. In most cases such problems are caused by the simple fact that somewhere among your CSS rules you’ve defined a more specific selector. This article has been updated on October 5th, 2016.
CSS Specificity isn’t simple. However, there are methods to explain it in a simple and intuitive way. And that’s what this article is all about. You’ll understand the concept if you love Star Wars. Really.
Further Reading on SmashingMag:
- CSS Specificity And Inheritance
- CSS Inheritance, The Cascade And Global Scope
- !important CSS Declarations: How and When to Use Them
- Challenging CSS Best Practices
Let’s take a look at some important issues related to CSS Specificity as well as examples, rules, principles, common solutions, and resources. You can find the most important things you should know about CSS specificity in a brief overview at the beginning of the article.
CSS Specificity: An Overview
- Specificity determines, which CSS rule is applied by the browsers.
- Specificity is usually the reason why your CSS-rules don’t apply to some elements, although you think they should.
- Every selector has its place in the specificity hierarchy.
- If two selectors apply to the same element, the one with higher specificity wins.
- There are four distinct categories which define the specificity level of a given selector: inline styles, IDs, classes, attributes, and elements.
- You can understand specificity if you love Star Wars: CSS Specificity Wars.
- You can understand specificity if you love poker: CSS Specificity for Poker Players
- When selectors have an equal specificity value, the latest rule is the one that counts.
- When selectors have an unequal specificity value, the more specific rule is the one that counts.
- Rules with more specific selectors have a greater specificity.
- The last rule defined overrides any previous, conflicting rules.
- The embedded style sheet has a greater specificity than other rules.
- ID selectors have a higher specificity than attribute selectors.
- You should always try to use IDs to increase the specificity.
- A class selector beats any number of element selectors.
- The universal selector and inherited selectors have a specificity of 0, 0, 0, 0.
- You can calculate CSS specificity with CSS Specificity Calculator.
What is Specificity?
If two CSS selectors apply to the same element, the one with higher specificity wins.
Specificity hierarchy
Every selector has its place in the specificity hierarchy. There are four distinct categories which define the specificity level of a given selector:
Inline styles (Presence of style in document). An inline style lives within your XHTML document. It is attached directly to the element to be styled. E.g.
<h1 style=“color: #fff;”>
IDs (# of ID selectors) ID is an identifier for your page elements, such as
#div
.Classes, attributes and pseudo-classes (# of class selectors). This group includes
.classes
,[attributes]
and pseudo-classes such as:hover
,:focus
etc.Elements and pseudo-elements (# of Element (type) selectors). Including for instance
:before
and:after
.
If you don’t know what exactly each of these terms stands for, you can take a look at the brief overview of them; in the last section of this article.
How to measure specificity?
Memorize how to measure specificity. “Start at 0, add 1000 for style attribute, add 100 for each ID, add 10 for each attribute, class or pseudo-class, add 1 for each element name or pseudo-element. So in
body #content .data img:hover
the specificity value would be 122 (0,1,2,2 or 0122): 100 for #content, 10 for .data, 10 for :hover, 1 for body and 1 for img.” [CSS Specificity]
Alternative way: “Count the number of ID attributes in the selector (= a). Count the number of other attributes and pseudo-classes in the selector (= b). Count the number of element names and pseudo-elements in the selector (= c). Concatenating the three numbers a-b-c gives the specificity. [CSS Selector Specificity]
CSS Specificity Wars - Cheat Sheet To help me understand calculating specificity better I made a chart based on the following specificity (or Sith power) values. Each character (selector) is given its own Sith power (specificity value) depending on how powerful they are in the ways of the Dark Side. A storm trooper is less powerful than Vader who is in turn less powerful than the Emperor.
Specificity Examples: Test Yourself
It’s easier to calculate the specificity using the first method. Let’s find out, how it actually is done.
1 | * { } | 0 |
2 | li { } | 1 (one element) |
3 | li:first-line { } | 2 (one element, one pseudo-element) |
4 | ul li { } | 2 (two elements) |
5 | ul ol+li { } | 3 (three elements) |
6 | h1 + *[rel=up] { } | 11 (one attribute, one element) |
7 | ul ol li.red { } | 13 (one class, three elements) |
8 | li.red.level { } | 21 (two classes, one element) |
9 | style=“” | 1000 (one inline styling) |
10 | p { } | 1 (one HTML selector) |
11 | div p { } | 2 (two HTML selectors) |
12 | .sith | 10 (one class selector) |
13 | div p.sith { } | 12 (two HTML selectors and a class selector) |
14 | #sith | 100 (one id selector) |
15 | body #darkside .sith p { } | 112 (HTML selector, id selector, class selector, HTML selector; 1+100+10+1) |
Specificity: Basic Principles
Equal specificity: the latest rule is the one that counts. “If you have written the same rule into your external style sheet twice, then the lower rule in your style sheet is closer to the element to be styled, it is deemed to be more specific and therefore will be applied. When selectors have an equal specificity value, such as
#content h1 {
padding: 5px;
}
#content h1 {
padding: 10px;
}
where both rules have the specificity 0, 1, 0, 1, the latter rule is always applied.
Specificity Rules
ID selectors have a higher specificity than attribute selectors. For example, in HTML, the selector #p123
is more specific than [id=p123]
in terms of the cascade. Example: in
A:
a#a-02 { background-image : url(n.gif); }
and
B:
a[id="a-02"] { background-image : url(n.png); }
the first rule (A) is more specific than the second one (B). [W3C CSS 2.1 Specification]
Contextual selectors are more specific than a single element selector. It also holds for other selectors involving more than one HTML element selector. [Cascade Inheritance]
The embedded style sheet is closer to the element to be styled. So in the following situation
CSS:
#content h1 {
padding: 5px;
}
(X)HTML:
<style type="text/css">
#content h1 {
padding: 10px;
}
</style>
the latter rule will be applied.
The last rule defined overrides any previous, conflicting rules. For example, given these two rules
p { color: red; background: yellow }
p { color: green }
…paragraphs would appear in green text. They would also have a yellow background, however, because the first rule is not completely negated. [BrainJar.com]
A class selector beats any number of element selectors. .introduction
beats html body div div h2 p
. [CSS Specificity for Poker Players]
The universal selector has a specificity of 0, 0, 0, 0. *
, body *
and similar selectors have a zero specificity. Inherited values also have a specificity of 0, 0, 0, 0. [CSS Specificity Clarified]
Specificity Example
Consider three code fragments:
A: h1
B: #content h1
C: <div id="content">
<h1 style="color: #fff">Headline</h1>
</div>
The specificity of A is 0,0,0,1 (one element), the specificity of B is 0,1,0,1 (one ID reference point and one element), the specificity value of C is 1,0,0,0, since it is an inline styling.
Since
0001 = 1 < 0101 = 101 < 1000,
…the third rule has a greater level of specificity, and therefore will be applied. If the third rule didn’t exist, the second rule would have been applied.
Specificity in Practice
Use LVHA for link styling. “To ensure that you see your various link styles, you’re best off putting your styles in the order “link-visited-hover-active”, or “LVHA” for short.” [Link Specificity]
Never use !important
.
“If you’re having specificity issues, there’s some quick ways to solve it. First, avoid !important
.” “The !important
declaration overrides normal declarations, but is unstructured and rarely required in an author’s style sheet.” [Understanding Specificity, Selector Specificity]
Use id to make a rule more specific.
Replacing a.highlight
with ul#blogroll a.highlight
changes the specificity from 0, 0, 1, 1 to 0, 1, 1, 2.
Minimize the number of selectors. “Use the least number of selectors required to style an element.” [Understanding Specificity]
CSS Specificity Tools & Resources
CSS Specificity for Poker Players If you’re not from the programming world and CSS seems a bit confusing, perhaps this analogy may help clear some concepts up. Think of CSS rules as poker hands. The best hand determines an element’s style.
CSS specificity calculator Calculates the specificity of a given selector.
Understanding Specificity Tutorial In this tutorial, you will look at specificity. Specificity is a type of weighting that has a bearing on how your cascading style sheet (CSS) rules are displayed. All rules in your style sheet carry a specificity rating regardless of selector type, although the weighting that is given to each selector type varies and will ultimately affect the styling of your web documents.
Cascade Inheritance: Specificity At this point, it might be timely to have a quick discussion of specificity. Both inside a single style sheet, and in a cascade of style sheets, it should be clear that more than one rule can apply to the same element. What happens when two properties in separate rules which both apply to an element contradict one another?
CSS 2.1 Selectors Explained
An extensive overview of CSS 2.1 selectors. Learning how to use the full range of CSS selectors available in CSS 2.1 properly can actually help you keep your HTML a lot cleaner. It will let you minimise unnecessary use of the class attribute and the need for adding extraneous div
and span
elements to the markup.
CSS Specificity Bugs in IE A brief overview of specificity bugs implemented in Microsoft Internet Explorer/Win.
CSS Structure and Rules Basic Syntax, Pseudo-classes and Pseudo-elements, Cascading Order.
Specificity It may not seem like something that important, and in most cases, you won’t come across any conflicts at all, but the larger and more complex your CSS files become, or the more CSS files you start to juggle with, the greater likelihood there is of conflicts turning up.
What is what?
A selector is the element that is linked to a particular style. E.g. p
in
p { padding: 10px; }
A class selector is a selector that uses a defined class (multiple per page). E.g. p.section
in
p.section { padding: 10px; }
An ID selector is a selector that uses an individually assigned identifier (one per page). E.g. p#section
in
CSS: #section { padding: 10px; }
(X)HTML: <p id="section">Text</>
A contextual selector is a selector that defines a precise cascading order for the rule. E.g. p span
in
p span { font-style: italic; }
defines that all span-elements within a p-element should be styled in italics.
An attribute selector matches elements which have a specific attribute or its value. E.g. p title
in
p[title] { font-weight: bold; }
matches all p-elements which have a title
attribute.
Pseudo-classes are special classes that are used to define the behavior of HTML elements. They are used to add special effects to some selectors, which are applied automatically in certain states. E.g. :visited
in
a:visited { text-decoration: underline; }
Pseudo-elements provide designers a way to assign style to content that does not exist in the source document. Pseudo-element is a specific, unique part of an element that can be used to generate content “on the fly”, automatic numbering and lists. E.g. :first-line
or :after
in
p:first-line { font-variant: small-caps; }
a:link:after { content: " (" attr(href) ")"; }