Units that matter — px vs rem vs em vs %, and why it's not just style

Which unit a value is written in isn't a stylistic preference — each one is anchored to a genuinely different reference point, and picking the wrong anchor is a real, common source of layouts that quietly break under settings the developer never tested.

Intermediate

3 min read

px: an absolute, fixed reference — deliberately immune to context

.border { border-width: 1px; } /* always exactly 1px, regardless of anything else on the page */

A pixel is anchored to nothing but itself — it doesn't scale with the user's font-size preference, the parent element, or anything else. This is exactly the right property for things that should genuinely never scale — a 1px hairline border is meant to stay a crisp 1px line regardless of what else is happening on the page — but it's the wrong choice for anything meant to respect a user's accessibility preferences, which is the throughline the rest of this lesson builds toward.

em: relative to the CURRENT element's own font-size — and it compounds

.card { font-size: 16px; }
.card .badge { font-size: 0.8em; padding: 0.5em; } /* 0.8em = 12.8px; 0.5em padding = 6.4px (half of 12.8px, not 16px) */

em is relative to the font-size of the element it's used on — for padding, that means the element's own (already-resolved) font-size, not its parent's. The real gotcha: if font-size itself is set in em on a nested element, each level compounds against the one above it — a 0.8em font-size nested three levels deep, each also 0.8em, ends up at 0.8 × 0.8 × 0.8 ≈ 0.51em of the original, not 0.8em — a genuinely surprising cascading shrink that's easy to lose track of in deeply nested components.

rem: relative to the ROOT element's font-size — flat, no compounding

html { font-size: 16px; } /* the single source of truth for every rem value on the page */
.badge { font-size: 0.8rem; } /* ALWAYS 12.8px, regardless of nesting depth or any ancestor's font-size */

rem ("root em") always resolves against the <html> element's font-size specifically, no matter how deeply nested the element using it is — which eliminates em's compounding problem entirely, while still scaling proportionally if the user (or the page) changes the root font-size. This is exactly why rem is the standard recommendation for most sizing in modern CSS: predictable like px, but still respectful of the user's font-size preferences the way px categorically isn't.

The accessibility reason this isn't just a style preference

/* A user who increases their browser's default font-size (a real, common
   accessibility accommodation for low vision) expects text AND layout
   sized in rem/em to scale accordingly. Text sized in px stays frozen
   at its original size regardless — the user's own OS/browser setting
   is silently ignored. */

Browsers let users set a default font-size preference, and rem/em values scale with that preference automatically, while px values do not — a real, measurable accessibility gap, not a theoretical one. This is the concrete, practical reason style guides for production sites commonly specify rem for font sizes and most spacing, reserving px specifically for things that have a genuine reason to stay fixed (hairline borders, an icon's exact pixel dimensions).

%: relative to the parent's resolved value of that same property

.sidebar { width: 250px; }
.sidebar .inner { width: 90%; } /* 90% of 250px = 225px — relative to the PARENT's width, specifically */

Percentage is contextual per-property: width: 90% is relative to the parent's width, but line-height: 150% is relative to the element's own font-size, not any parent measurement — the reference point genuinely depends on which property % is applied to, which is worth checking per-property rather than assuming a single universal rule.

Further reading

Check your understanding

A quick comprehension check — not tracked, not graded, just for you.

1. Why can nested `em` font-sizes produce a surprising cascading shrink?

2. Why does `rem` avoid the compounding problem that `em` has?

3. Why is using rem/em for font sizes considered an accessibility practice, not just a style choice?