Specificity
Try it yourself!View all demos
Specificity is a mechanism within the CSS cascade that aids conflict resolution. The concept of specificity states that when two or more declarations that apply to the same element, and set the same property, have the same importance and origin, the declaration with the most specific selector will take precedence.
Consider this example:
p {
color: black;
background-color: white;
}
div.warning p {
color: red;
}
div#caution p {
color: yellow;
}
body#home div p {
color: white;
}
The above example style sheet contains four style rules that have a
selector that matches p elements. Because one of those
rules has an element type selector p, it’s
guaranteed that two or more rules will apply to the same
p element, and because they all contain a
color property declaration, the user agent needs a way
to determine which of the declarations should be applied. What will the
final color value be for the p
element?
The simple answer is that the more specific selector’s declaration will take precedence. The user agent calculates each selector’s specificity so that a comparison can be made, and resolves the deadlock by choosing the declaration whose selector has the highest specificity.
Calculating Specificity
Here’s a simplified description of the process by which the specificity of the selectors of two or more declarations is compared:
- If one declaration is from a
styleattribute, rather than a rule with a selector (an inline style), it has the highest specificity. If none of the declarations are inline, proceed to step two. - Count the ID selectors. The declaration with the highest count has the highest specificity. If two or more have the same number of ID selectors, or they all have zero ID selectors, proceed to step three.
- Count the class selectors
(for example,
.test), attribute selectors (for example,[type="submit"]), and pseudo-classes (for example,:hover). The declaration with the highest total has the highest specificity. If two or more have the same total, or they all have totals of zero, proceed to step four. - Count the element type
selectors (for example
div) and pseudo-elements (for example,:first-letter). The declaration with the highest total has the highest specificity.
If two or more selectors have the same specificity, then, according to the rules of the CSS cascade, the latter specified rule takes precedence.
If you want to be technical, the W3C recommendation (6.4.3) describes the method
for calculating a selector’s specificity. The result of this calculation
takes the form of four comma-separated values,
a,b,c,d,1
where the values in column “a” are the most important and
those in column “d” are least important. A selector’s
specificity is calculated as follows:
- To calculate
a, count 1 if the declaration is from astyleattribute rather than a rule with a selector (an inline style), 0 otherwise. - To calculate
b, count the number of ID attributes in the selector. - To calculate
c, count the number of other attributes and pseudo-classes in the selector. - To calculate
d, count the number of element names and pseudo-elements in the selector.
The result of counting these elements is not a score, but a matrix of values that can be compared column by column. As an example, consider the following rule which contains an element type selector from the previous example:
p {
color: black;
background-color: white;
}
If we try to work out the specificity of the above selector on
the basis of the specificity formula, we arrive at a result that looks
like 0,0,0,1, as it has one element name.
As we
said before, this is not a number but four comma-separated values, where
the values in column a (inline styles) are the most
important, and those in column d (element names and
pseudo-elements) are the least important. When comparing selectors to
determine which has the highest specificity, look from left to right, and
compare the highest value in each column. So a value in column
b will override values in columns c and
d, no matter what they might be. As such, specificity of
0,1,0,0 would be greater than one of
0,0,10,10.
Specificity Step by Step
Let’s try and break down each part of the calculation procedure so that it’s more understandable.
The first step is to calculate the value for column
a, which we’ve done in Inline Style: Column a = 1. If the style rule is specified within the
element’s HTML style attribute, a
should equal 1; otherwise, it should equal
0. In fact, this is the only case where there is a value
in column a.
| Inline Style | IDs | Classes, Attributes, and Pseudo-classes | Element Types and Pseudo-elements |
|---|---|---|---|
| 1 | 0 | 0 | 0 |
As you can see, an inline style rule will always have a
specificity of 1,0,0,0—the highest level of specificity.
Here’s an example of such a style rule:
<p style="color:red;">Red Text</p>
This
is one of the reasons why inline styles should be avoided. As inline style
rules always have the highest specificity, the only way to overwrite them
within the CSS cascade is to use the !important
statement on the relevant declarations—an approach that creates a
maintenance nightmare.
For rules other than inline styles, we need
to calculate columns b, c, and
d. Let’s run through a full calculation for the following
rule:
body#home div#warning p.message {
color: red;
}
The above rule has a selector, body#home
div#warning p.message, and a single declaration,
color: red;. Since this isn’t an inline style, we start
off with a 0 in the first column, as Column a = 0 shows.
| Inline Style | IDs | Classes, Attributes, and Pseudo-classes | Element Types and Pseudo-elements |
|---|---|---|---|
| 0 | ? | ? | ? |
To calculate the value for column b, we
count the number of ID selectors in the selector. In our selector,
body#home div#warning p, there are
two—#home and
#warning—thus, column b is
equal to 2, as is depicted in Column b = 2.
| Inline Style | IDs | Classes, Attributes, and Pseudo-classes | Element Types and Pseudo-elements |
|---|---|---|---|
| 0 | 2 | ? | ? |
Next, we calculate the value for column c,
counting the number of class selectors, attribute selectors, and
pseudo-classes in the selector.
Note that [id="foo"] is not equivalent
to #foo—you can see there’s a significant
difference in their levels of specificity.
In our example selector, body#home
div#warning p.message, there’s one class selector,
.message, so, as you can see in Column c = 1, c is equal to
1.
| Inline Style | IDs | Classes, Attributes, and Pseudo-classes | Element Types and Pseudo-elements |
|---|---|---|---|
| 0 | 2 | 1 | ? |
Finally, for column d, we count the number
of element type selectors and pseudo-elements in the selector. In our
example selector, body#home div#warning
p.message, there are three: body,
div, and p. There
are no pseudo-elements to be counted, so we put a 3 in
the last column, as Column d = 3
shows.
| Inline Style | IDs | Classes, Attributes, and Pseudo-classes | Element Types and Pseudo-elements |
|---|---|---|---|
| 0 | 2 | 1 | 3 |
We now have our result. The specificity for the selector
body#home div#warning p.message can be
expressed as: 0,2,1,3.
All right, let’s consider a
crazy situation where more than half a dozen color declarations for the
same p element have the same levels of importance and
origins. Which color would the browser apply to the element?
Here’s our crazy style sheet:
p.message {
color: green;
}
#home #warning p.message {
color: yellow;
}
#warning p.message {
color: white;
}
body#home div#warning p.message {
color: blue;
}
p {
color: teal;
}
* body#home>div#warning p.message {
color: red;
}
#warning p {
color: black;
}
We should be able to use the specificity calculation method to
work out which of the declarations would be applied. But, wait a minute!
What are the levels of specificity of the universal selector,
*, and the child combinator,
>?
The answer is that they don’t have any specificity at all; they’re simply ignored in all calculations. This is true for all combinators, which you can treat as though they had a specificity of zero, as they will make no difference to your calculation. After all, five out of the seven selectors above use the descendant combinator and you weren’t worried about those!
See if you can work out the specificity of all the selectors above for yourself before looking at the answer in Selector Specificity Results.
| Selector | Inline Style | IDs | Classes, Attributes, and Pseudo-classes | Element Types and Pseudo-elements |
|---|---|---|---|---|
body#home div#warning
p.message |
0 | 2 | 1 | 3 |
* body#home>div#warning
p.message |
0 | 2 | 1 | 3 |
#home #warning
p.message |
0 | 2 | 1 | 1 |
#warning p.message |
0 | 1 | 1 | 1 |
#warning p |
0 | 1 | 0 | 1 |
p.message |
0 | 0 | 1 | 1 |
p |
0 | 0 | 0 | 1 |
The results have been ordered according to specificity—the
highest are at the top, and the lowest are at the bottom. As you can see,
the top two selectors have exactly the same specificity, despite the extra
universal selector and combinator in one of them. In this case, they tie
for specificity and the one that appears last in the style sheet will be
the winner. If you look at the original style sheet source above, the red
color will be applied to the p element.
You can
see from Selector Specificity Results that
the selector p.message has a lower specificity
than the selector #warning p. This is a common
cause of head scratching among those new to CSS, who often think that a
class selector will be specific enough to match an element in all
cases.
Footnotes
1 This is different from the CSS1 specification, in which specificity took the form of a number score, as explained at http://www.w3.org/TR/CSS1#cascading-order.
User-contributed notes
- ID:
- #3
- Date:
- Mon, 03 Mar 2008 16:15:33 GMT
- Status:
- This note has not yet been confirmed for accuracy and relevance.
Incorrect: "(an inline style)" should be placed directly after "style attribute", instead of after "rather than a rule with a selector".
As it is now it seems the rule with a selector is being labeled as an inline style.
Add a note
To post a note on this topic, please log in with your SitePoint username and password. If you don't have an account yet, you can create a new account for free.
