CSS Specificity Tutorial: How Specificity Works in CSS with Examples

calender-iconPublished: 23 Jun 2025

clock-icon5-min read





INTRODUCTION

CSS specificity is a scoring system that browsers use to determine which CSS rule should be applied when multiple rules could affect the same element. Think of it as a weight or priority system where more specific selectors override less specific ones.

When the browser encounters conflicting CSS rules, it doesn't just apply the last one it reads. Instead, it calculates the specificity of each rule and applies the one with the highest specificity score.

The Specificity Hierarchy

CSS specificity follows a four-category hierarchy, often represented as four numbers: a, b, c, d where:

  • a = Inline styles → counts as 1 if present, otherwise 0
  • b = Number of ID selectors
  • c = Number of class selectors, attributes, and pseudo-classes
  • d = Number of element selectors and pseudo-elements
1. Inline Styles (a = 1)

Inline styles have the highest specificity value of 1-0-0-0. These are styles applied directly to an element using the style attribute.

2. IDs (b = 1)

ID selectors have a specificity value of 0-1-0-0. Each ID selector adds 0-1-0-0 to the specificity score.

3. Classes, Attributes, and Pseudo-classes (c = 1)

This category includes class selectors, attribute selectors, and pseudo-classes, each contributing 0-0-1-0 to the specificity score.

4. Elements and Pseudo-elements (d = 1)

Element selectors and pseudo-elements have the lowest specificity value of 0-0-0-1.

5. The !important Declaration

The !important declaration overrides normal specificity calculations. It gives a rule the highest priority, regardless of specificity.

6. Universal Selector and Combinators

The universal selector (*), combinators (+, ~, >), and negation pseudo-class (:not()) don't add to specificity.

7. Inherited Styles

Inherited styles have no specificity. Any directly targeted rule, regardless of how low its specificity, will override inherited styles.

Examples
Example 1
h1 {color: blue; }

  • No inline styles → a = 0
  • No ID → b = 0
  • No class/attribute/pseudo-class → c = 0
  • One element → d = 1
Specificity: (0, 0, 0, 1)


Example 2
.card .title { font-size: 18px; }

  • No inline → a = 0
  • No ID → b = 0
  • Two classes → .card and .title → c = 2
  • No element → d = 0
Specificity: (0, 0, 2, 0)


Example 3
#main-nav a { color: teal; }

  • No inline → a = 0
  • one ID → #main-nav → b = 1
  • No classes → c = 0
  • one element → anchor → d = 1
Specificity: (0,1,0,1)


Example 4
nav ul li a { color: brown; }

  • No inline styles → a = 0
  • No ID → b = 0
  • No class/attribute/pseudo-class → c = 0
  • Four element → d = 4
Specificity: (0, 0, 0, 4)


!important

The !important declaration is a special rule in CSS used to give higher priority to a specific CSS property. When a style is marked with !important, it overrides all other conflicting rules, even those with higher specificity, unless another rule also has !important.

Syntax

selector {
  property: value !important;
}

Example - This ensures that all paragraph elements will have red text, even if there are other rules trying to set the color to something else.


p {
  color: red !important;
}
What If Two Rules Have !important?

When two CSS rules both use !important, the browser will still need to decide which one wins. In this case, the normal specificity rules and source order are used to resolve the conflict. Let’s break it down:

  • Compare specificity - The rule with the higher specificity takes precedence.
  • If specificity is equal, check source order - The rule that appears later in the stylesheet or in a stylesheet that is included later will win.

Example - The color will be blue, because #header has higher specificity than .main-title.


<style>
  #header {
    color: blue !important; /* Specificity: 0,1,0,0 */
  }

  .main-title {
    color: red !important;  /* Specificity: 0,0,1,0 */
  }
</style>

<h1 id="header" class="main-title">Hello!</h1>


!important impact on cascade origin order

The !important rule in CSS alters the normal cascade order, especially in the context of origin order. Here's a detailed explanation of how it affects the cascade origin hierarchy:

CSS Cascade Origins (from lowest to highest priority):
  1. User Agent Styles (browser defaults)
  2. User Styles (set by the user in browser settings)
  3. Author Styles (your CSS)
  4. Author Styles with !important
  5. User Styles with !important
  6. User Agent Styles with !important (rarely relevant)
Origin Without !important Priority With !important Priority
User Agent Styles 1 (lowest) 6 (highest) (rare)
User Styles 2 5
Author Styles 3 4


!important impact on Cascade Layers

In normal styles (without !important), the browser follows the order in which layers are created. The first layer written has the lowest priority, and the last one has the highest. Any styles that are not inside a layer come after all the layered styles.

But for styles marked with !important, the order is flipped. All !important styles that are not inside a layer are grouped together in a hidden layer. This group is stronger than all normal styles, but weaker than any !important styles inside layers.

Among !important layered styles, the ones in layers declared earlier have higher priority than those in layers declared later.

Frequently Asked Questions (FAQ)

What is the difference between specificity and the cascade in CSS?
In CSS, specificity and the cascade are two separate but related concepts that determine which styles are ultimately applied to an element when there are conflicting rules.

1. Specificity
Specificity is a score (or weight) calculated based on the type of CSS selectors used. It helps the browser decide which rule takes precedence when multiple rules target the same element.

2. Cascade
The cascade is the overall algorithm CSS uses to resolve conflicts between multiple rules that apply to the same element. It takes multiple factors into account in a particular order: Cascade decision hierarchy:
  1. Origin and importance
    1. User-agent styles (browser default)
    2. User styles
    3. Author styles (your CSS)
    4. !important rules override others (but are still affected by specificity and layer order)
  2. Specificity (as explained above)
  3. Source order – If rules have equal specificity, the one that comes last in the CSS file wins.

Does !important override specificity?
Yes — !important can override specificity, but not always. Let’s break this down clearly:

1. A CSS declaration with !important will override other declarations even if they have higher specificity.

2. If two rules both use !important, then specificity matters again.


#box {
  color: blue !important;
} /* Specificity: 100, important */

p {
  color: red !important;
} /* Specificity: 1, important */

Now, color: blue will apply because both are !important, so the more specific selector wins.
Case Winner
!important vs. normal rule !important wins
!important vs. higher specificity !important still wins
!important vs. !important Rule with higher specificity wins
Equal !important and specificity Rule declared later in source wins

What is the order of precedence in CSS selectors?
Represents Specificity Value Example
Inline styles (1, 0, 0, 0) style="color: red"
ID selectors (0, 1, 0, 0) #main, #header
Classes, attributes, pseudo-classes (0, 0, 1, 0) .btn, [type="text"], :hover
Elements and pseudo-elements (0, 0, 0, 1) div, h1, ::before

How to increase CSS specificity?
Action Effect on Specificity Example
Add ID selector Increases by 100 #header .btn
Add class/attribute/pseudo-class Increases by 10 .btn.primary:hover
Add element selector Increases by 1 h1 strong
Use inline style Increases to 1000 style="color:red"
Use !important Overrides all (not specificity-based) color: red !important
Use :where() No specificity added :where(.low)

How to decrease CSS specificity?
Method Description Example
Use fewer selectors Simplify the selector chain h1 instead of #header h1
Remove ID selectors IDs have very high specificity Use .header instead of #header
Use class instead of inline style Avoid style="" unless absolutely necessary Use .text-red in CSS
Use cascade layers Place lower-priority styles in earlier layers @layer base { ... }
Use :where() pseudo-class Zero-specificity wrapper that doesn't affect specificity :where(.low-priority)
How can I override CSS specificity?
Overriding CSS specificity can be tricky, especially when dealing with highly specific or conflicting rules. Here’s a practical breakdown of how you can override CSS specificity effectively:
  • Use !important - Forces a rule to win regardless of specificity.
  • Use a more specific selector - Make your selector more specific than the one you're trying to override.
  • Match the same specificity and place the rule later - CSS honors the rule that comes later in source order when specificity is equal.
  • Use :where() to lower specificity - :where() adds zero specificity, so it’s easily overridden.
  • Move the rule to a higher cascade layer - If using cascade layers (@layer), unlayered or later-layer rules can override earlier ones, regardless of specificity.
  • Use inline styles - Inline styles have a very high specificity (1,0,0,0).
  • Use ID selectors (if really necessary) They have higher specificity than classes and elements.