Get Specific with Your CSS Styles

Share this article

Other than being the C in the acronym CSS, the fact that style sheets are described as “cascading” refers to an important, if complex, part of the way styles are applied to the elements in a document. It’s called the CSS cascade because style declarations cascade down to elements from many origins.

The cascade combines many factors in order to determine exactly — and without conflict — which declaration should be applied to any given element. The factors influencing whether a style rule takes effect or not are the importance, origin, source order, and (possibly the most misunderstood, and poorly documented factor) specificity.

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.

This article is taken from SitePoint’s The Ultimate CSS Reference, which is available free online, and can be purchased in hard-cover print format.

Calculating Specificity

Here’s a simplified description of the process by which the specificity of the selectors of two or more declarations is compared:

  1. If one declaration is from a style attribute, 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.

  2. 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.

  3. 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.

  4. 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. (This is different from the CSS1 specification, in which specificity took the form of a number score, as explained at https://www.w3.org/TR/CSS1#cascading-order.) Here, 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 a style attribute 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 Table 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.

Table 1. Inline Style: Column a = 1 Inline Style

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 Table 2 shows.

Table 2. Column a = 0 Inline Style

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 Table 3.

Table 3. Column b = 2

Next, we calculate the value for column c, counting the number of class selectors, attribute selectors, and pseudo-classes in the selector.

Attribute Selectors for IDs
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 Table 4, c is equal to 1.

Table 4. Column c = 1 Inline Style

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 Table 5 shows.

Table 5. Column d = 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 Table 6.

Table 6. Selector Specificity Results

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 Table 6 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.

To learn more about the CSS language, visit the online reference, and check out the hard-cover edition.

Frequently Asked Questions about CSS Specificity

What is CSS Specificity and why is it important?

CSS Specificity is a set of rules used in CSS (Cascading Style Sheets) to decide which style rule applies to an element when multiple rules are applicable. It’s important because it determines how conflicts in CSS rules are resolved. The rule with the highest specificity will be applied, overriding any other conflicting rules. Understanding CSS Specificity is crucial for effective web design and development, as it helps you control the look and feel of your web pages more precisely.

How is CSS Specificity calculated?

CSS Specificity is calculated based on the different types of selectors used in a CSS rule. Each type of selector has a different specificity value. Inline styles have the highest specificity, followed by ID selectors, class selectors, attribute selectors, and pseudo-classes, and finally, type selectors and pseudo-elements. The specificity of a CSS rule is the sum of the specificity values of its selectors.

Can I override CSS Specificity?

Yes, you can override CSS Specificity by using the !important rule. When you add !important to a CSS rule, it will override any other rule, regardless of its specificity. However, use !important sparingly as it can make your CSS harder to manage and debug.

What is the role of inheritance in CSS Specificity?

Inheritance is a key concept in CSS that affects specificity. When an element doesn’t have a specific style rule, it will inherit the style of its parent element. However, an explicit rule with a higher specificity will override inherited styles.

How can I check the specificity of my CSS rules?

You can check the specificity of your CSS rules by using online tools like CSS Specificity Calculator. These tools allow you to input your CSS and they will calculate the specificity for you.

What is the difference between class and ID selectors in terms of CSS Specificity?

In terms of CSS Specificity, ID selectors have a higher specificity than class selectors. This means that if you have conflicting rules, the rule with the ID selector will be applied.

How does the order of CSS rules affect specificity?

The order of CSS rules can affect specificity when two rules have the same specificity. In such cases, the rule that comes last in the CSS file will be applied.

What are pseudo-classes and pseudo-elements in CSS Specificity?

Pseudo-classes and pseudo-elements are special types of selectors in CSS. Pseudo-classes select elements based on their state, like :hover or :focus, while pseudo-elements select a specific part of an element, like ::before or ::after. In terms of CSS Specificity, both have the same specificity as class selectors.

Can I use multiple selectors in a single CSS rule? How does it affect specificity?

Yes, you can use multiple selectors in a single CSS rule. The specificity of such a rule is the sum of the specificity of its selectors. This allows you to create more specific rules when needed.

What are some best practices for managing CSS Specificity?

Some best practices for managing CSS Specificity include avoiding the use of !important, keeping your CSS selectors as simple as possible, using class selectors instead of ID selectors for styling, and understanding the role of inheritance in CSS.

SitePoint TeamSitePoint Team
View Author

Sharing our passion for building incredible internet things.

Share this article
Read Next
Get the freshest news and resources for developers, designers and digital creators in your inbox each week