Skip to main content

Specificity Hierarchy

Selectors carry different "weights", and every type of CSS selector holds a position in the specificity hierarchy. From strongest to weakest:

  • Inline styles — top priority, overriding all other selectors.
  • ID selectors (e.g. #navbar) — next in priority, weighing 1-0-0.
  • Classes, attribute selectors, and pseudo-classes (e.g. .test, [type="text"], :hover) — third in priority, weighing 0-1-0.
  • Element selectors and pseudo-elements (e.g. <h1>, ::before, ::after) — low priority, weighing 0-0-1.
  • Universal selector (*) and :where() — no priority, weighing 0-0-0.

Understand the Weight Notation

A weight is written as three numbers (X-Y-Z), and each one counts a group of selectors:

  • X — ID selectors.
  • Y — class selectors, attribute selectors, and pseudo-classes.
  • Z — element selectors and pseudo-elements.

Comparison starts on the left, so a higher leftmost number wins outright. On a tie, the next number decides, and so on.


Calculate the Specificity Weight

An element receives the CSS declaration whose specificity weight is the highest.

Example

Several selectors of different weights target the same paragraph here, which shows how the specificity hierarchy plays out. With a weight of 1-0-1, the highest of them, p#demo wins.

Prompt
Create a page that demonstrates CSS specificity hierarchy weights. Define multiple CSS rules targeting the same paragraph: an ID selector (#demo), a combined selector (p#demo), a class selector (.test), a combined class selector (p.test), and an element selector (p). The paragraph should have id="demo" and class="test", and display "Hello World!" in the color of the highest-specificity rule (orange from p#demo with weight 1-0-1). Add CSS comments showing each rule's weight.
Output: complete HTML page

More Specificity Examples

The scenarios below show how specificity behaves in a few other situations, to help it sink in.

Equal specificity: the latest rule wins

When a rule appears twice in the style sheet, the one written last wins.

Prompt
Create a page showing that when two CSS rules have equal specificity, the last rule wins. Define two h1 rules: the first sets background-color to yellow, and the second sets background-color to red. Display an h1 heading to show the red background wins.
Output: complete HTML page

ID selectors beat attribute selectors

Even when an attribute selector targets the ID of the element, an ID selector outranks it on specificity, so the rule of the ID selector is the one applied.

Prompt
Create a page demonstrating that an ID selector has higher specificity than an attribute selector. Use #myDiv with background-color yellow and div[id=myDiv] with background-color blue. Show a div element with id="myDiv" to prove the ID selector wins (yellow background).
Output: complete HTML page

A class selector beats element selectors

Element selectors like <h1>, <p>, and <div> all lose to a class selector such as .intro.

Prompt
Create a page showing that a class selector beats an element selector. Define .intro with background-color yellow and h1 with background-color red. Display an h1 element with class="intro" to demonstrate the class selector wins (yellow background).
Output: complete HTML page

The universal selector (*)

Because the universal selector (*) carries no specificity weight value, every other selector overrides it.

Prompt
Create a page demonstrating that the universal selector (*) has no specificity weight. Define * with background-color yellow and h1 with background-color red. Display an h1 heading to show the element selector wins over the universal selector (red background).
Output: complete HTML page

Embedded style vs external style sheet

Given the same specificity, an embedded style sheet beats an external one when it is closer to the element, since it appears later.

index.html
/*From external CSS file:*/
#content h1 {background-color: red;}

/*In HTML file:*/
<style>
#content h1 {background-color: yellow;}
</style>