Why is my CSS not applying?

Short answer

A more specific selector elsewhere is winning. Count specificity as (inline, IDs, classes/attributes/pseudo-classes, elements) and compare left to right — the first difference decides.

SelectorSpecificity
p0,0,0,1
.card0,0,1,0
.card p0,0,1,1
.card.is-active0,0,2,0
#main .card0,1,1,0
style="…"1,0,0,0

Higher wins. When two selectors tie exactly, the one written later wins.

#Diagnose it in DevTools

Inspect the element and look at the Styles panel. Overridden declarations are shown with a strikethrough, and the rule that won is at the top. That tells you in two seconds what guessing takes twenty minutes to find.

#Common causes that are not specificity

  • A typo in the class name, or the class not actually on the element.
  • The stylesheet did not load — check the Network tab for a 404.
  • The property does not apply to that element. width does nothing on an inline element; give it display: inline-block or block.
  • A shorthand later reset it. background: red clears background-image.
  • The value is invalid. One bad declaration is dropped silently; the rest of the rule still applies.

#Do not reach for !important

It wins, but it starts an arms race — the next override needs !important too, and now nothing can be adjusted normally. Instead:

Lower the specificity of the winning rule. #main .card almost never needs the ID.

Raise yours minimally. .card.card is a legitimate trick: repeating a class doubles its specificity without adding an ID.

Use :where() for zero-specificity defaults. Everything inside :where() counts as 0, which makes base styles trivially overridable:

css
:where(.prose) a { color: blue; }   /* any single class beats this */

#Layers make it explicit

css
@layer base, components, utilities;

Later layers beat earlier ones regardless of specificity. This is the modern answer to the whole problem.