Specificity and the Cascade
How the browser decides which rule wins when multiple rules target the same element.
読了時間 2 分
When two rules target the same element with conflicting declarations, the browser needs a tie-breaker. That tie-breaker is a combination of specificity, source order, and !important — together known as the cascade.
Specificity, roughly
Specificity is calculated per selector as a score with three tiers, from highest to lowest weight:
- ID selectors (
#header) - Class, attribute, and pseudo-class selectors (
.card,[type="text"],:hover) - Element and pseudo-element selectors (
p,::before)
p {
color: black;
}
.warning {
color: red;
}
#alert-box {
color: orange;
}If one element matched all three rules, #alert-box would win — an ID selector outranks a class, which outranks an element selector, regardless of the order the rules appear in.
Adding up compound selectors
.card .title {
color: blue;
}
.title {
color: green;
}.card .title has two class selectors, .title has one — so .card .title wins even though .title alone looks simpler. Specificity is compared tier-by-tier (count of IDs, then classes, then elements), not by counting total selectors, but for everyday CSS the intuition "more classes chained together = more specific" is a reasonable shortcut.
Source order is the fallback
p {
color: blue;
}
p {
color: green;
}When two rules have equal specificity, the one that appears later in the stylesheet (or in a later linked stylesheet) wins. This is why a small change of moving a <link> tag or reordering rules can silently change how a page looks — the specificity was tied, and order broke the tie.
!important breaks the rules — carefully
.button {
color: white !important;
}!important overrides normal specificity entirely: a declaration marked !important wins over any non-!important declaration, no matter how specific the other selector is. It's a blunt tool that's easy to reach for under deadline pressure and painful to undo later, because the only way to override an !important rule is with another !important rule of equal or higher specificity. Treat it as a last resort, not a shortcut.
Practical takeaway
Most specificity bugs come from fighting the cascade instead of working with it: an ID selector used for styling that later needs a one-off override, or a deeply nested selector that's harder to beat than intended. Favor flat, class-based selectors (a single class per rule where possible) — they keep specificity low and predictable, so the natural source-order cascade does the work instead of you needing tricks to win.