rem scales with the reader's font size, px does not, and em compounds when you nest it. The differences are small until an accessibility audit, so here is the rule for each one.
The CSS Unit Converter converts between all of these, and its base field is the root font size the conversion assumes — 16 by default, because that is the default in every major browser.
px — a CSS pixel, defined as 1/96 inch at a normal viewing distance. It is not a device pixel; on a phone one CSS px covers two or three hardware pixels.rem — the root font size, i.e. the computed font-size of <html>. One value for the whole document.em — the font size of the current element. Nest two elements that both use em and the effect multiplies.% — depends entirely on the property. For font-size it is the parent's font size; for width it is the containing block; for line-height it is the element's own font size.pt — a print unit, 1/72 inch, which works out to 1.333px at 96dpi. Use it in print stylesheets and nowhere else.This is the part most explanations get slightly wrong. A reader who sets their browser's default font size to 20px is telling every site to start from 20px. Type sized in rem follows that. Type sized in px ignores it completely and stays exactly as you specified.
Page zoom is different: zoom scales px along with everything else, so a px-based layout is not unusable — it simply overrides a preference the reader already expressed, and forces them to zoom the entire page when all they wanted was larger text.
That is the whole argument for rem on anything text-sized. It is not about pixel-perfection; it is about not discarding a setting the user deliberately changed.
Use em when something should scale with nearby text rather than with the document. Padding inside a button, the gap between an icon and its label, a border-radius that should stay proportional to a label — all of these read better in em, because bumping the button's font-size carries them along automatically.
The failure mode is nesting. Give <li> a font-size: 0.9em and a list three levels deep is at 0.73em without anyone deciding that. Type scales belong in rem for exactly this reason.
Setting html { font-size: 62.5%; } makes 1rem equal 10px on a default browser, so 1.4rem reads as 14px and the mental arithmetic disappears. Because 62.5% is relative to the reader's default rather than a fixed 10px, it still honours their preference — it is a legitimate technique, not a hack that breaks accessibility.
The catch is that every third-party stylesheet on the page now computes rem against 10px too, and component libraries generally assume 16. Set the base to 10 in the converter to model this before committing to it.
Inside a media query, em and rem both resolve against the initial font size — the browser default or the user's preference — never against whatever you set on <html>. So the 62.5% trick does not shift your breakpoints, and @media (min-width: 40em) means 640px for a default reader and 800px for someone running a 20px default. That is usually what you want, and it is always surprising the first time.