rem vs em.
Root-relative vs parent-relative.
1rem is always the same. 1em is different depending on where you are in the DOM. That's the whole difference — and it matters more than it sounds. This page covers why rem is the default for font sizes and spacing, when em is the right choice, and the compounding problem that makes em hard to predict in nested layouts.
Short answer: rem = root-relative. 1rem is always the root font size (usually 16px), regardless of where the element is. em = parent-relative. 1em is the parent's font size — so it changes with nesting. Use rem for font sizes, spacing, and layout — anything that should be consistent. Use em for component-relative sizing (button padding that scales with text). Never use px for font sizes — it breaks user preferences.
✅ Before and after
The same nested elements, with rem and em.
html {
font-size: 16px;
}
.parent {
font-size: 1.2em; /* 16 × 1.2 = 19.2px */
}
.child {
font-size: 1.2em; /* 19.2 × 1.2 = 23.04px */
}
.grandchild {
font-size: 1.2em; /* 23.04 × 1.2 = 27.648px */
}
Nesting depth vs font size: Depth 0 (html): 16px Depth 1 (.parent): 19.2px ← 1.2 × 16 Depth 2 (.child): 23.04px ← 1.2 × 19.2 Depth 3 (.grandchild): 27.65px ← 1.2 × 23.04 Each level multiplies by 1.2. ❌ The same CSS declaration produces different font sizes depending on depth. ❌ "Why is my text getting bigger as I nest?" ❌ You have to know every ancestor's font size. This is em compounding. It's not a bug — it's how em works. But it's hard to predict.
html {
font-size: 16px;
}
.parent {
font-size: 1.2rem; /* 16 × 1.2 = 19.2px */
}
.child {
font-size: 1.2rem; /* 16 × 1.2 = 19.2px */
}
.grandchild {
font-size: 1.2rem; /* 16 × 1.2 = 19.2px */
}
Nesting depth vs font size: Depth 0 (html): 16px Depth 1 (.parent): 19.2px Depth 2 (.child): 19.2px Depth 3 (.grandchild): 19.2px Every level = 1.2rem = 1.2 × 16 = 19.2px. ✅ The same CSS declaration produces the same size at every depth. ✅ Predictable — 1.2rem is 19.2px, always. ✅ Easy to reason about. ✅ Matches what designers expect. This is why rem is the default unit for font sizes and spacing.
✅ When em is the right choice
Component-relative sizing.
.button {
font-size: 1rem;
padding: 0.5em 1em; /* scales with font-size */
border-radius: 0.25em;
border: 1px solid currentColor;
}
.button--large {
font-size: 1.5rem;
/* padding and border-radius automatically scale
to 0.75rem 1.5rem and 0.375rem */
}
/* Icon size matching text */
.icon {
width: 1em;
height: 1em;
vertical-align: -0.125em;
}
/* Responsive padding based on viewport /
.container {
padding: 2em; / scales if font-size is changed /
}
Why em works for buttons: Button default (font-size: 1rem): padding: 0.5em 1em → 8px 16px border-radius: 0.25em → 4px Button large (font-size: 1.5rem): padding: 0.5em 1em → 12px 24px ← automatically! border-radius: 0.25em → 6px ← automatically! ✅ Change font-size, everything scales. ✅ One set of styles, multiple sizes. ✅ The padding is proportional to the text. This is the correct use of em — component styles that intentionally scale with font size. If you used rem for the padding, the large button would look cramped — the text would be 1.5× but the padding would stay the same. Rule: em for component-internal proportions, rem for everything else.
Don't use em for font sizes in nested components. The compounding effect means a font-size: 1.2em on a deeply nested element can be 2× the size of the same declaration on a shallow one. This makes typography unpredictable — you set 1.2em, you get 23px in one place and 40px in another. Use rem for font sizes (consistent, root-relative, respects user settings), and reserve em for spacing inside a component (padding, border-radius) where you want the scaling. The rule of thumb: rem for layout, em for component internals.
⚠️ Common mistakes
The rem/em mistakes that cost real time.
Compounds with nesting. Fix: rem for font sizes.
Depends on root font-size. Fix: check html { font-size } or user settings.
Breaks user font-size preferences. Fix: rem.
Makes 1rem = 10px — but breaks user preferences and screen readers. Fix: leave html at default or 100%.
Same project uses both without a rule. Fix: pick a convention (rem for layout, em for internals).
Compounds with nesting. Fix: rem for margin.
Unitless line-height is relative to font size — works with rem or em. Fix: line-height: 1.5 (unitless).
rem in media queries uses the root font size, not the user's font size. Fix: understand this before using rem breakpoints.
❓ Frequently asked
What is the difference between rem and em?
rem is relative to the root element's font size — usually html { font-size: 16px }. 1rem = 16px everywhere, regardless of nesting. em is relative to the parent element's font size — 1em is the current font size of the parent, which could be anything. This is the key difference: rem is consistent across the page, em compounds with nesting.
Why does em compound?
Because em is relative to the parent's font size, which is relative to its parent, which is relative to its parent — all the way up to the root. If body is font-size: 16px, and a div is font-size: 1.2em (19.2px), and a child is font-size: 1.2em (23.04px), and a grandchild is 1.2em (27.648px), each level multiplies. This is often called 'the em cascade' or 'em compounding.'
When should I use rem?
Use rem for anything that should be consistent across the page: font sizes, spacing (padding, margin, gap), widths and heights, border-radius, box-shadow offsets. If you set html { font-size: 16px }, then 1rem = 16px, 2rem = 32px, everywhere. rem also respects user accessibility settings: if the user changes their browser's default font size, rem scales with it.
When should I use em?
Use em when a size should scale with the parent's font size. Classic use cases: (1) Button padding — if the button font-size is 1rem, padding: 0.5em 1em gives 8px × 16px padding; if the font is 1.5rem, padding scales to 12px × 24px. (2) Border-radius that stays proportional to text. (3) Icon sizes that should match adjacent text. em is the right tool when the design intentionally couples two sizes.
Is 1rem always 16px?
No — 1rem is always equal to the root element's font size, which is usually 16px but can be anything. If you set html { font-size: 62.5% }, then 1rem = 10px. If you set html { font-size: 20px }, then 1rem = 20px. The default in most browsers is 16px, but users can change it in their browser settings — this is a feature, not a bug.
Should I use rem, em, or px?
Use rem for font sizes, spacing, and most layout dimensions. Use px only for things that should never scale: hairlines (1px borders), very fine details. Use em for component-relative sizing (button padding that scales with font, icon sizes that match text). Never use px for font sizes — it breaks user font-size preferences.