A badge placed inside a card, itself placed inside a list, can end up displaying text oddly larger or smaller than expected if every level uses em for its font size: each value multiplies against the level above it, and the effect compounds without any single rule looking wrong on its own.
rem was introduced precisely to avoid that compounding effect, by giving the whole page one shared reference instead of a chain of nested references.
Definition
em is computed against the font size of the element itself when used for anything other than font-size, or against the parent's when it is used to set font-size itself. rem, short for "root em", is always computed against the font size of the document's root element, usually html, no matter how deeply nested it is.
html {
font-size: 16px; /* the single reference for rem */
}
.card {
padding: 1.5rem; /* always 24px, no matter where the card sits */
}The compounding effect of em
When several nested levels each set their own font-size in em, each value multiplies against its parent's, not against the root's font size.
.list {
font-size: 1.2em; /* x1.2 relative to its parent */
}
.list .list {
font-size: 1.2em; /* x1.2 relative to .list, so x1.44 overall */
}
.list .list .list {
font-size: 1.2em; /* x1.2 again, so x1.728 overall */
}Three nested list levels, each perfectly reasonable on its own, produce text almost twice as large as expected at the third level.
font-size property itself, em is computed against the parent, since the element's own size is not known yet. On any other property such as padding or width, em is computed against the already-determined font size of the element itself, not its parent.rem: a single reference, no accumulation
rem completely ignores nesting depth: whether the element sits directly under body or buried ten div levels deep, 2rem always equals twice the font size set on the root. That is what makes it the recommended default for line-height and for a project's font-size scale.
Where em still earns its place
em stays relevant when a spacing needs to stay proportional to the font size of the component carrying it, rather than to the whole page. A button whose padding is written in em keeps consistent proportions if its own "large" variant simply bumps up its font-size, with no need to recompute the padding separately. Our HTML and CSS course builds that exact kind of multi-size button component, to show exactly where em takes over from rem.
.button {
font-size: 1rem;
padding: 0.6em 1.2em; /* follows the button's size, not the page's */
}
.button--large {
font-size: 1.25rem; /* the padding grows with it automatically */
}Frequently asked questions
padding written in em change size when I never touched it?Because an ancestor changed its own font size, and em stays relative to the effective font size of the element carrying it. The padding then follows that indirect change, even though no rule on the padding itself moved.
rem always better than em?No, for typography and global spacing, yes almost always. But for a spacing that needs to stay proportional to one specific component, like a button or a badge, em is exactly what avoids recomputing every size variant by hand.
Both rem and em follow that setting, since they both ultimately trace back to the browser's default font size. A site built in px for its text, on the other hand, ignores that accessibility setting entirely, whatever the reader has configured.