How to Calculate CSS Specificity Score

CSS specificity is the algorithm web browsers use to determine which style rules apply to an element when multiple conflicting declarations exist. This article breaks down the calculation formula for IDs, classes, and element tags, explaining how to tally selector values and compare scores to resolve styling conflicts efficiently.


The Specificity Formula: (A, B, C)

CSS specificity is calculated using a three-component score represented in a tuple format: (A, B, C).

Each column represents a category of selector, counted from highest priority to lowest:

  • A (ID Selectors): Counts each ID selector (e.g., #header, #main).
  • B (Class, Attribute, and Pseudo-class Selectors): Counts each class (e.g., .btn), attribute selector (e.g., [type="text"]), and pseudo-class (e.g., :hover, :focus).
  • C (Type and Pseudo-element Selectors): Counts each HTML element tag (e.g., div, h1, p) and pseudo-element (e.g., ::before, ::after).

Mathematical Representation

\[\text{Specificity} = (\text{Total IDs},\ \text{Total Classes},\ \text{Total Elements})\]


How Comparison Works

Specificity scores are evaluated from left to right, comparing each position individually:

  1. Compare Column A (IDs): The rule with more IDs wins.
  2. Compare Column B (Classes): If Column A is tied, the rule with more classes wins.
  3. Compare Column C (Elements): If Column A and B are tied, the rule with more element selectors wins.
  4. Tie-Breaker (Source Order): If all three values are identical, the rule declared later in the CSS file takes precedence.

Note: Values do not carry over. A selector with 1 ID (1, 0, 0) will always override a selector with 10 or more classes (0, 10, 0).


Examples in Practice

CSS Selector IDs (A) Classes (B) Elements (C) Total Score
nav ul li a 0 0 4 (0, 0, 4)
ul.menu li a 0 1 3 (0, 1, 3)
.menu a:hover 0 2 1 (0, 2, 1)
#sidebar .widget 1 1 0 (1, 1, 0)
#header #nav.fixed 2 1 0 (2, 1, 0)

Analysis

  • .menu a:hover (0, 2, 1) overrides ul.menu li a (0, 1, 3) because Column B is higher (2 > 1).
  • #sidebar .widget (1, 1, 0) overrides both, because it contains an ID in Column A (1 > 0).

Selectors with Zero Specificity

Certain selectors add no weight to the calculation and evaluate to (0, 0, 0):

  • Universal selector: *
  • Combinators: >, +, ~, and the space (descendant) combinator
  • The :where() pseudo-class: Any selectors inside :where() are assigned zero specificity.

Outside the Standard Formula

  • Inline Styles: Styles added directly to an HTML element (e.g., style="color: red;") sit outside the standard three-part score, effectively functioning as a fourth column at the far left: (1, 0, 0, 0). They override any selector targeting the element through external or internal stylesheets.
  • !important: Declarations appended with !important do not add to the specificity score. Instead, they override all normal specificity calculations and standard inline styles.