CSS Specificity Calculator

CSS specificity determines which rule wins when multiple selectors target the same element, scored as (a, b, c) where a = ID selectors, b = class selectors, attribute selectors, and pseudo-classes, and c = type selectors and pseudo-elements. For example, #header .nav a has a specificity of (1, 1, 1) because it contains one ID, one class, and one element. Higher specificity always wins regardless of source order. Enter a CSS selector below to calculate its specificity instantly.

Quick Answer

The selector #header .nav a has a specificity of (1, 1, 1). The selector .sidebar .widget h3 has a specificity of (0, 2, 1). An ID selector always outweighs any number of classes.

CSS Selector

Common Examples

Input Result
#header .nav a (1, 1, 1) - score 111
.sidebar .widget h3 (0, 2, 1) - score 21
div p (0, 0, 2) - score 2
#main #content .article h1 (2, 1, 1) - score 211
a:hover (0, 1, 1) - score 11

How It Works

CSS specificity is the algorithm browsers use to determine which CSS declaration applies when multiple rules target the same element. It is calculated from the selector and expressed as a three-part value (a, b, c).

The Three Categories

a: ID selectors count the number of #id selectors. Each ID contributes 1 to the first position.

b: Class-level selectors count the number of .class selectors, [attribute] selectors, and pseudo-classes like :hover, :focus, :nth-child(), etc. Each one contributes 1 to the second position.

c: Element-level selectors count the number of type selectors (div, p, h1) and pseudo-elements (::before, ::after, ::first-line). Each one contributes 1 to the third position.

Comparison Rules

Specificity is compared left to right. A selector with (1, 0, 0) always beats (0, 99, 99) because the first column (IDs) is compared first. If the first column ties, the second column is compared, and so on. If all columns are equal, the rule that appears later in the source wins.

Special Cases

  • The universal selector (*) has zero specificity
  • Combinators (>, +, ~, space) do not affect specificity
  • :not() itself adds no specificity, but the selector inside it does
  • :where() and its contents have zero specificity
  • :is() and :has() take the specificity of their most specific argument
  • Inline styles override all selector-based specificity (conceptually a fourth column)
  • !important overrides everything, including inline styles

Worked Example

For the selector #main .content ul > li.active a:hover:

  • IDs: #main = 1
  • Classes and pseudo-classes: .content, .active, :hover = 3
  • Elements: ul, li, a = 3

Specificity = (1, 3, 3), score = 133.

Compared to .sidebar .widget .list a which has specificity (0, 3, 1), score = 31. The first selector wins because it has 1 ID vs 0 IDs, regardless of the other columns.

Practical Tips

To keep specificity manageable, avoid deeply nested selectors and limit ID usage in CSS. Many methodologies like BEM (Block Element Modifier) use only class selectors, keeping all specificity at the (0, n, 0) level. This makes the cascade predictable and overrides straightforward.

Related Calculators

Frequently Asked Questions

Why does one ID beat any number of classes?
Specificity is compared column by column from left to right. The ID column (a) is compared before the class column (b). A selector with specificity (1, 0, 0) beats (0, 255, 0) because the first column comparison (1 vs 0) determines the winner immediately. The remaining columns are never reached.
How does !important interact with specificity?
!important overrides the normal specificity cascade entirely. An !important declaration on a low-specificity rule beats a high-specificity rule without !important. When multiple !important declarations compete, normal specificity rules apply among them. Using !important frequently leads to difficult-to-maintain CSS.
Do pseudo-elements and pseudo-classes have the same specificity?
No. Pseudo-classes (:hover, :focus, :nth-child()) count as class-level selectors in column b. Pseudo-elements (::before, ::after, ::first-line) count as element-level selectors in column c. A pseudo-class has higher specificity weight than a pseudo-element.
What is the specificity of inline styles?
Inline styles (the style attribute on an HTML element) override all selector-based specificity. They are conceptually in a fourth column that outranks IDs. Only !important can override an inline style. In practice, avoid inline styles when possible to keep styles maintainable.
How does the :where() pseudo-class affect specificity?
The :where() pseudo-class and everything inside it has zero specificity. This makes it useful for writing default styles that are easy to override. For example, :where(.card) h2 has specificity (0, 0, 1) because the .card inside :where() contributes nothing. Without :where(), .card h2 would have specificity (0, 1, 1).