Beginner9 min read

CSS Specificity Explained: How Browsers Decide Which Styles Win

9 min read
344 words
15 sections12 code blocks

What is CSS Specificity?

CSS specificity is a system that determines which CSS rule takes priority when multiple rules target the same element. When two or more conflicting styles apply to an element, the browser uses specificity to decide which style wins.

Why Specificity Matters

Understanding specificity is crucial because it explains why some of your CSS styles seem to be "ignored" by the browser. Most CSS debugging problems come down to specificity conflicts.

CSS
/* Which color will the paragraph be? */
p { color: blue; }
.intro { color: green; }
#welcome { color: red; }
HTML
<p class="intro" id="welcome">Hello World</p>

The paragraph will be red because the ID selector has the highest specificity.

The Specificity Hierarchy

CSS specificity is calculated based on the types of selectors used. Think of it as a scoring system with four levels:

Level 1: Inline Styles (Highest)

Inline styles written directly on an HTML element have the highest specificity.

HTML
<p style="color: red;">This will always be red</p>

Level 2: ID Selectors

ID selectors, such as #header or #main-content, carry a very high level of specificity.

CSS
#header { color: blue; }

Level 3: Class, Attribute, and Pseudo-Class Selectors

These include .classname, [attribute], :hover, :first-child, etc.

CSS
.nav-link { color: green; }
[type="text"] { border: 1px solid gray; }
a:hover { color: orange; }

Level 4: Element and Pseudo-Element Selectors (Lowest)

These include p, div, h1, ::before, ::after, etc.

CSS
p { color: black; }
h1 { font-size: 2rem; }

Calculating Specificity

Specificity is often represented as a four-part value: (inline, IDs, classes, elements)

CSS
/* (0, 0, 0, 1) - one element */
p { }

/* (0, 0, 1, 0) - one class */
.intro { }

/* (0, 1, 0, 0) - one ID */
#header { }

/* (0, 0, 1, 1) - one class + one element */
p.intro { }

/* (0, 1, 1, 1) - one ID + one class + one element */
div#header.active { }

/* (0, 0, 2, 1) - two classes + one element */
ul.nav .nav-item { }

Specificity Rules in Practice

Rule 1: Higher specificity always wins

CSS
.card .title { color: blue; }    /* (0,0,2,0) */
.title { color: red; }           /* (0,0,1,0) */
/* Blue wins - higher specificity */

Rule 2: Equal specificity - last one wins

CSS
.title { color: blue; }   /* (0,0,1,0) */
.title { color: red; }    /* (0,0,1,0) */
/* Red wins - it comes last */

Rule 3: !important overrides everything

CSS
.title { color: red !important; }
#header .title { color: blue; }
/* Red wins - !important overrides specificity */

The Universal Selector and Combinators

The universal selector (*), combinators (>, +, ~), and the :not() pseudo-class do NOT add to specificity.

CSS
* { }                  /* (0,0,0,0) */
div > p { }            /* (0,0,0,2) - only div and p count */
:not(.active) { }      /* (0,0,1,0) - only .active counts */

Avoiding Specificity Wars

Here are best practices to avoid specificity conflicts:

  • Use classes instead of IDs for styling
  • Keep selectors short and simple
  • Avoid !important unless absolutely necessary
  • Use a consistent naming pattern, such as BEM (Block Element Modifier).
  • Use a logical source order in your stylesheet
CSS
/* BAD: Too specific, hard to override */
div#main-content ul.nav li.nav-item a.nav-link { color: blue; }

/* GOOD: Simple and maintainable */
.nav-link { color: blue; }

Summary

CSS specificity determines which styles are applied when multiple rules conflict. Remember the hierarchy: inline styles > IDs > classes > elements. Keep your selectors simple, prefer classes over IDs, and avoid !important to write maintainable CSS that is easy to debug and override.