CSS Selector Specificity Calculation Rules
CSS selector specificity is the core mechanism that determines which rule takes effect when multiple rules target the same HTML element. Its calculation is based on the specificity and weight of the selectors.
1. The Concept and Necessity of Specificity
When multiple CSS declarations target the same HTML element simultaneously, the browser needs a set of rules to decide which style is ultimately applied. This set of rules is called "Specificity." Rules with higher specificity override those with lower specificity.
2. Specificity Weight Levels
Specificity is compared using a sequence of four parts, which can be represented as (a, b, c, d). When comparing, proceed from left to right: the rule with the higher a-value has the highest priority. If a is equal, compare b, and so on. These four parts are:
- a: Inline Styles - Styles written directly in the
styleattribute of an HTML element. Highest weight. - b: Number of ID Selectors - The count of ID selectors (e.g.,
#header) in the selector. - c: Number of Class Selectors, Attribute Selectors, and Pseudo-classes - Includes class selectors (e.g.,
.button), attribute selectors (e.g.,[type="text"]), and pseudo-classes (e.g.,:hover,:nth-child(n)). - d: Number of Element Selectors and Pseudo-elements - Includes element (tag) selectors (e.g.,
div,p) and pseudo-elements (e.g.,::before,::after).
Note: The universal selector (*), combinators (e.g., +, >, ~), and the negation pseudo-class (:not()) themselves do not contribute to specificity weight. However, the selectors inside :not() do count.
3. Calculation Steps and Example
Let's learn how to calculate through a concrete example. Assume the following CSS rules and HTML:
/* Rule 1 */
#nav .list li a {
color: red;
}
/* Rule 2 */
body header ul li a.link {
color: blue;
}
/* Rule 3 */
a.link:hover {
color: green;
}
<body>
<header id="nav">
<ul class="list">
<li><a id="home" class="link" href="#" style="color: yellow;">Home</a></li>
</ul>
</header>
</body>
Now, we need to determine the color of the <a> tag. Calculate the specificity for each rule:
-
Rule 1:
#nav .list li a- a (Inline styles): 0
- b (ID selectors): 1 (
#nav) - c (Class/Attr/Pseudo-class): 1 (
.list) - d (Element/Pseudo-element): 2 (
li,a) - Specificity: (0, 1, 1, 2)
-
Rule 2:
body header ul li a.link- a: 0
- b: 0
- c: 1 (
.link) - d: 5 (
body,header,ul,li,a) - Specificity: (0, 0, 1, 5)
-
Rule 3:
a.link:hover- a: 0
- b: 0
- c: 2 (
.link,:hover) - d: 1 (
a) - Specificity: (0, 0, 2, 1)
-
Inline Style on the Element
- In the HTML, the element has
style="color: yellow;". - The a-value for inline styles is 1.
- Specificity: (1, 0, 0, 0)
- In the HTML, the element has
4. Specificity Comparison and Result
Now compare the four specificity values:
- Rule 1: (0, 1, 1, 2)
- Rule 2: (0, 0, 1, 5)
- Rule 3: (0, 0, 2, 1)
- Inline style: (1, 0, 0, 0)
During comparison, first compare the a-values. The inline style's a=1 is significantly greater than all other rules' a=0. Therefore, the inline style has the highest priority. So, the final link color is yellow.
If we remove the inline style style="color: yellow;" and compare again:
- Rule 1: (0, 1, 1, 2)
- Rule 2: (0, 0, 1, 5)
- Rule 3: (0, 0, 2, 1)
Now compare a-values, all are 0. Next, compare b-values. Rule 1's b=1 is greater than Rule 2 and Rule 3's b=0. Therefore, Rule 1 has the highest priority, and the link color will become red.
5. The Important Rule (!important)
This is a special case. Adding !important after a style declaration grants it the highest priority, overriding all other declarations (including inline styles). However, it is strongly advised to use it with extreme caution, as it breaks the cascading nature of CSS, making debugging and maintenance very difficult. The best practice is to rely on proper specificity calculations to solve problems.
Summary:
When calculating specificity, remember the weight hierarchy a > b > c > d. By breaking down the selector into these four parts and counting, you can accurately predict the outcome of any style conflict.