Selector Specificity: The Cascading Algorithm and Specificity Weights
Master CSS Specificity. Learn the mathematical algorithm browsers use to calculate specificity weights, manage inheritance, and avoid !important traps.
Introduction
Have you ever written a CSS rule like .text-blue { color: blue; }, refreshed your browser, and noticed the text remains black? You open the DevTools inspector, locate the element, and see your new rule crossed out with a line.
This happens because another CSS rule targeting that same element has a higher Specificity.
Specificity is the mathematical algorithm browsers use to determine which CSS rule is "most specific" to an element, and therefore which style declaration wins. If you do not understand how these weights are calculated, you will find yourself in a constant battle against your own stylesheet, desperately throwing !important flags at your selectors.
What You Will Learn
- How the browser calculates specificity weights.
- The 4-digit specificity coordinate system.
- How inheritance and the Cascade resolve style conflicts.
- The dangers of the
!importantflag and how to use it safely. - Practical specificity calculation scenarios.
Prerequisites
Detailed Explanation: The Specificity Formula
When multiple rules target the same element, the browser calculates a weight score represented by a 4-digit tuple:
$$\text{Specificity} = (\text{Inline}, \text{IDs}, \text{Classes}, \text{Elements})$$
Let's break down each column value:
- Inline Styles (1, 0, 0, 0): Added directly to the HTML tag using the
styleattribute. - ID Selectors (0, 1, 0, 0): Targeted using the hash symbol (e.g.
#header). - Class Selectors, Attributes & Pseudo-Classes (0, 0, 1, 0): Targeted using periods, brackets, or colons (e.g.
.btn,[type="text"],:hover). - Element Selectors & Pseudo-Elements (0, 0, 0, 1): Targeted using tags or double colons (e.g.
div,p,::before).
Note: The Universal Selector (*) and combinators (like +, >, ~) have a specificity score of exactly (0, 0, 0, 0).
Specificity Comparison (Who Wins?)
When comparing two selectors, evaluate the coordinates from left to right:
-
Scenario A:
- Selector 1:
#global-nav .menu-item$\rightarrow$ Score:(0, 1, 1, 0) - Selector 2:
body nav ul li .menu-item$\rightarrow$ Score:(0, 0, 1, 4) - Winner: Selector 1. An ID score
(1)in the second column immediately defeats any number of classes and elements in the subsequent columns.
- Selector 1:
-
Scenario B:
- Selector 1:
.card .title$\rightarrow$ Score:(0, 0, 2, 0) - Selector 2:
.card h2$\rightarrow$ Score:(0, 0, 1, 1) - Winner: Selector 1. Two classes beat one class and one element.
- Selector 1:
What is the Cascade?
If two selectors target the same element and have the exact same specificity score, the browser uses the Cascade rule:
- The rule declared lowest (last) in the stylesheet wins.
The !important Rule
Adding !important at the end of a declaration overrides all specificity calculations, including inline styles.
/* Avoid doing this unless absolutely necessary */
.alert {
color: red !important;
}
- The Trap: If you need to override an
!importantrule later, you must write another!importantrule with higher specificity. This creates a chain of unmaintainable declarations. - Valid Use Case: Overwriting third-party widget styles (like embedded forms or chat bubbles) where you cannot edit the HTML markup.
Visual Learning Diagram (Mermaid)
graph TD
A[Conflict: Multiple styles on 1 element] --> B{Does any rule use !important?}
B -->|Yes| C[Apply !important rule]
B -->|No| D{Compare Specificity Scores}
D -->|Inline styles win| E[Style applied]
D -->|IDs win| E
D -->|Classes/Pseudo-classes win| E
D -->|Element tags win| E
D -->|Tie: Identical Score| F[Cascade Rule: Last declared style wins]
Specificity Calculation Practice
Let's calculate the specificity scores for common selectors:
| Selector | Inline | ID | Class/Pseudo | Element/Pseudo | Score |
| :--- | :---: | :---: | :---: | :---: | :---: |
| div | 0 | 0 | 0 | 1 | (0, 0, 0, 1) |
| .menu li a | 0 | 0 | 1 | 2 | (0, 0, 1, 2) |
| header #logo | 0 | 1 | 0 | 1 | (0, 1, 0, 1) |
| nav ul li a:hover | 0 | 0 | 1 | 4 | (0, 0, 1, 4) |
| <h1 style="color: blue;">| 1 | 0 | 0 | 0 | (1, 0, 0, 0) |
Summary
Selector specificity is a mathematical coordinate comparison (Inline, IDs, Classes, Elements) evaluated from left to right. When specificity levels tie, the Cascade rule applies the last declared stylesheet rule. Developers prioritize class-based styling rules and minimize !important overrides to maintain clean codebases.
Related Articles
Next Tutorial
Congratulations! You have completed the Syntax & Selectors module. Let's move on to coloring and designing backgrounds using: CSS Colors.