Selectors and specificity
The selector vocabulary — combinators, attributes, pseudo-classes — plus a reliable way to reason about specificity.
Core selectors
| Selector | Matches |
|---|---|
* | Every element (universal) |
.card | Any element with class 'card' |
#header | The element with that id |
a:hover | Anchor while hovered (pseudo-class) |
p::first-line | First line of a paragraph (pseudo-element) |
[type='submit'] | Any element with that attribute value |
/* AND: both classes on the same element */
.btn.primary { }
/* descendants vs direct children */
.nav a { } /* any depth inside .nav */
.nav > a { } /* only one level down */
/* siblings */
h2 + p { } /* the paragraph right after an h2 */
h2 ~ p { } /* every paragraph after an h2 */Scoring specificity
Think of specificity as three counters — (inline, IDs, classes) then element count. Compare left to right; the first difference decides the winner.
| Selector | Score | Notes |
|---|---|---|
style='…' | 1-0-0-0 | Inline wins over everything except !important |
#main .card a | 0-1-1-1 | One id, one class, one element |
.card a.active | 0-0-2-1 | Two classes, one element |
ul li a | 0-0-0-3 | Elements only — weakest |
💡
:hover, :focus, [type='text'] and ::before each count in the class column. :not() does not add weight itself — its argument does.Writing selectors that survive
- Prefer a single class — flat specificity makes overrides predictable.
- Keep selectors short; long descendant chains couple your CSS to your HTML structure.
- Use
:is()to group alternatives without inflating specificity. - Naming conventions (BEM, utility classes) exist mostly to keep specificity flat by construction.
/* flat and predictable */
.card { }
.card--featured { }
/* grouped with :is() */
:is(h1, h2, h3) { line-height: 1.2; }FAQ
Why does .a .b beat .b?
Two classes outweigh one. Specificity is additive, so nesting quietly raises specificity — a common reason overrides mysteriously fail.
id or class for styling?
Use classes. An id selector carries heavy weight (0-1-0-0) that you will regret the first time you need to override it.
Related
CSS: getting started The box model
Last refreshed 2026-09-17.