The following is an extract from our book, CSS Master, written by Tiffany B. Brown. Copies are sold in stores worldwide, or you can buy it in ebook form here.
Think of specificity as a score or rank that determines which style declarations are ultimately applied to an element. The universal selector (*
) has low specificity. ID selectors are highly specific. Descendant selectors such as p img
and child selectors such as .panel > h2
are more specific than type selectors such as p
, img
, or h1
.
Calculating exact specificity values seems tricky at first. As explained in Selectors Level 3, you need to:
count the number of ID selectors in the selector (= A)
count the number of class selectors, attribute 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
These A, B, and C values are then combined to form a final specificity value. An ID selector such as #foo
has a specificity of 1,0,0. Attribute selectors, such as [type=email]
and class selectors such as .chart
have a specificity of 0,1,0. Adding a pseudo-class such as :first-child
(for example, .chart:first-child
) gives us a specificity of 0,2,0. But using a simple type or element selector such as h1
or p
only gives us a specificity of 0,0,1.
Note: Calculating Specificity
Keegan Street’s Specificity Calculator and Joshua Peek’s CSS Explain are helpful for learning about and calculating selector specificity.
Complex and combinator selectors, of course, give us higher specificity values. Let’s look at an example. Consider the following CSS:
ul#story-list > .book-review {
color: #0c0;
}
#story-list > .book-review {
color: #f60;
}
These two rule sets are similar, but they are not the same. The first selector, ul#story-list > .bookreview
, contains a type selector (ul
), an ID selector, (#story-list
), and a class selector (.bookreview
). It has a specificity value of 1,1,1. The second selector, #story-list > .book-review
only contains an ID and a class selector. Its specificity value is 1,1,0. Even though our #story-list > .book-review
rule succeeds ul#story-list > .bookreview
, the higher specificity of the former means that those elements with a .book-review
class will be green rather than orange.
Pseudo-classes such as :link
or :invalid
have the same level of specificity as class selectors. Both a:link
and a.external
have a specificity value of 0,1,1. Similarly, pseudo-elements such as ::before
and ::after
are as specific as type or element selectors. In cases where two selectors are equally specific, the cascade kicks in. Here’s an example:
a:link {
color: #369;
}
a.external {
color: #f60;
}
If we applied this CSS, every link would be slate blue except for those with class="external"
applied. Those links would be orange instead.
Keeping specificity low helps prevent selector creep, or the tendency for selector specificity and length to increase over time. This often happens as you add new developers to a team, or new forms of content to a website. Selector creep also contributes to long-term maintenance headaches. You either end up using more specific selectors to override other rule sets, or needing to refactor your code. Longer selectors also increase the weight of your CSS files.
We discuss strategies for keeping specificity low in Chapter 2.
Conclusion
After reading this chapter, you should have a good understanding of CSS selectors. Specifically, you should now know how to:
-
use selectors to apply CSS to particular elements, pseudo-elements, and pseudo-classes
-
understand the difference between pseudo-elements and pseudo-classes
-
employ newer pseudo-classes introduced by the Selectors Level 3 and 4 specifications
-
calculate specificity
In the next chapter, we’ll address some golden rules for writing maintainable, scalable CSS.
Frequently Asked Questions (FAQs) about CSS Selectors and Specificity
What is the importance of understanding CSS specificity in web development?
CSS specificity is a crucial concept in web development as it determines which CSS rule is applied by the browsers. When multiple CSS rules can apply to a certain element, the browser follows the specificity rule to decide which one to use. Understanding CSS specificity helps developers to write more efficient and effective CSS code, avoid unnecessary overwriting, and troubleshoot CSS issues more effectively.
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 you explain the concept of CSS specificity with an example?
Let’s consider an example. Suppose we have a CSS rule with a class selector .class1
and another rule with an ID selector #id1
. If these two rules can apply to the same element, the rule with the ID selector will be applied because ID selectors have higher specificity than class selectors.
What happens when two CSS rules have the same specificity?
When two CSS rules have the same specificity, the rule that comes last in the CSS code will be applied. This is because CSS follows a “last rule wins” policy when dealing with rules of the same specificity.
How can I override CSS specificity?
You can override CSS specificity by increasing the specificity of your CSS rule. This can be done by adding more specific selectors to your rule. Another way to override CSS specificity is by using the !important
rule. However, using !important
should be avoided as much as possible as it can make your CSS code harder to manage and debug.
What is the role of inheritance in CSS specificity?
Inheritance is a feature in CSS where some specific types of properties are automatically passed from a parent element to its child elements. However, inherited styles have the lowest specificity and can be easily overridden by any direct style applied to the element.
How does the universal selector affect CSS specificity?
The universal selector (*) has no effect on CSS specificity. This means that it has a specificity value of 0,0,0,0. Therefore, any other selector used in the same rule will override the universal selector.
What is the specificity of pseudo-elements in CSS?
Pseudo-elements in CSS have a specificity of 0,0,0,1. This means they have the same specificity as type selectors (like div
, p
, etc.) and are overridden by class selectors, ID selectors, and inline styles.
How does the :not()
pseudo-class affect CSS specificity?
The :not()
pseudo-class in CSS does not add to the specificity of a selector. Instead, the specificity is calculated based on the argument passed to the :not()
function. For example, in :not(.class1)
, the specificity is the same as that of .class1
.
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 all its selectors. For example, in #id1.class1
, the specificity is the sum of the specificity of #id1
and .class1
.
Tiffany B. Brown is a freelance web developer and technical writer based in Los Angeles. Brown offers web development and consulting services to larger agencies and small businesses. A former member of the Opera Software developer relations team, Brown is also co-author of SitePoint's JumpStart HTML5 book. She sporadically writes about web development technology on her blog. You can follow her on Twitter at @webinista.