← Back to CSS Course | Chapter 6: Selectors & Styling | Lesson 16 of 22

CSS Specificity Hierarchy

CSS Specificity already covers the basic four-part scoring and the !important exception — this topic goes into the trickier edge cases: compound selectors, the zero-specificity :where() trick, and how to actually debug a specificity fight in DevTools.

Compound Selector Specificity Adds Up

A compound selector like div.card.featured combines an element, and two classes, and its specificity is the sum of each part: one element point plus two class points. Developers often underestimate how quickly specificity accumulates when selectors get chained together.

Example: Compound Selector Specificity Adds Up

css
<style>
div.card { color: black; }
div.card.featured { color: gold; }
</style>
<div class="card featured">Two classes plus an element: highest specificity wins</div>

The :where() Zero-Specificity Trick

The :where() pseudo-class wraps a selector list but contributes zero specificity of its own, unlike :is() which takes the specificity of its highest-specificity argument. This makes :where() useful for writing default/reset styles that are trivially easy for any other rule to override.

Example: The :where() Zero-Specificity Trick

css
<style>
:where(.reset) p { color: black; }
.card p { color: blue; }
</style>
<div class="reset card"><p>Trivially overridden by any other rule</p></div>

Attribute and Pseudo-Class Selectors Count as Classes

Attribute selectors like [type="text"] and pseudo-classes like :hover or :nth-child() all count at the same specificity level as a regular class selector, one point each. This is easy to forget when a :hover rule unexpectedly fails to override a class-based rule of equal weight.

Example: Attribute and Pseudo-Class Selectors Count as Classes

css
<style>
.field { border-color: gray; }
[type="text"] { border-color: blue; }
</style>
<input type="text" class="field">

Debugging Specificity Conflicts in DevTools

Browser DevTools shows every matching CSS rule for a selected element with strikethrough on any declaration that lost to a higher-specificity or later rule. Reading this panel from top to bottom is the fastest real-world way to diagnose why a style is not applying, rather than guessing.

Example: Debugging Specificity Conflicts in DevTools

css
<style>
p { color: black; }
.text { color: green; }
</style>
<p class="text">DevTools shows the losing rule with a strikethrough</p>

Inline Styles and !important Interaction

An inline style attribute normally outranks every selector in a stylesheet regardless of specificity, since it is treated as specificity (1,0,0,0). However, !important on a stylesheet rule outranks even inline styles, making !important genuinely the highest-priority override in the entire specificity system.

Example: Inline Styles and !important Interaction

css
<style>
p { color: green !important; }
</style>
<p style="color: orange;">!important outranks even this inline style</p>

Login to run this code

C/C++/Java/PHP execution requires a free account. Your code is saved — you'll land right back in the editor after logging in.