px vs rem vs em
Short answer
Use rem for almost everything — font sizes, spacing, gaps and breakpoints — because it scales with the reader's browser font-size setting. Use px only for things that should never scale, such as a 1px border. Use em for the rare case where a value should track the element's own text size, like padding inside a button.
Side by side
| px | rem | em | |
|---|---|---|---|
| Relative to | Nothing — it is absolute | The root element's font size | The current element's font size |
| 1 unit at default settings | 1px | 16px | 16px, unless the element sets its own size |
| Compounds when nested | No | No | Yes — this is the main gotcha |
| Respects browser font-size setting | No | Yes | Yes |
| Predictable anywhere in the document | Yes | Yes | No — depends on ancestors |
| Good for font sizes | No | Yes | Sometimes |
| Good for borders and shadows | Yes | No | No |
| Good for media query breakpoints | Works, but ignores user preference | Yes | Yes |
When to use each
Use rem when…
Your default for anything related to reading: font sizes, padding and margins around text, gaps, border-radius and breakpoints. It scales with the reader's preference and means the same thing everywhere in the document.
Use px when…
Things that should stay exactly as drawn regardless of text size — hairline borders, precise shadow offsets, and small decorative details where scaling produces blurry sub-pixel edges.
Use em when…
Values that should scale with the element's own text rather than the page. Button padding is the classic example: a larger button label should get proportionally larger padding automatically.
The difference that actually matters
All three describe a length, so the question is never really 'which unit is better' — it is 'relative to what?'. px is relative to nothing; it is an absolute value that renders the same regardless of context. rem is relative to the root element's font size, so it means the same thing in every part of the document. em is relative to the font size of the element it appears on, which means its value changes depending on where it is used.
That last property is why em surprises people. Set a list to font-size: 0.9em, nest another list inside it at 0.9em, and the inner one computes to 0.81em. A third level drops to 0.73em. Nothing is broken; em is doing exactly what it says, but the effect compounds through nesting in a way that is hard to predict when the markup is deep.
Why px is an accessibility problem for text
Browsers let people change their default font size, and a meaningful number of readers do — because of low vision, a high-resolution display, or simple preference. Changing that setting changes what 1rem resolves to. It does not change what 16px resolves to.
So a layout built in px ignores that preference entirely, and the text stays exactly as small as it was designed. This is distinct from page zoom, which scales everything including px; the font-size preference is the one px silently defeats, and it is the setting people with low vision are most likely to have changed.
That is the whole case for rem. It is not about the numbers being nicer — it is that rem honours a setting the reader deliberately chose, and px does not.
The 62.5% trick, and why to skip it
A popular technique sets html { font-size: 62.5% } so that 1rem equals 10px and the arithmetic becomes trivial — 2.4rem is obviously 24px.
It works, but it does so by overriding the reader's chosen default before scaling from it, which discards the main reason to use rem at all. Someone who set their default to 20px now gets 12.5px as their base instead.
Leave the root font size alone and convert the numbers instead. That way the reader's preference is preserved and your type scale still lands where you designed it.
Frequently asked questions
Is 1rem always 16px?
Should breakpoints be in px or rem?
Does using px hurt SEO?
What about vw, vh, ch and %?
Try the PX to REM Converter
Convert pixels to rem or rem back to pixels at any root font size, with a full conversion table for the common values.