rem vs em vs px: CSS Units Explained
px is a fixed unit, em scales to a parent's font size, and rem scales to the root. How to choose between them for sizing and typography in CSS.
px is an absolute unit that always renders at the same fixed size. em is relative to the font size of the current element’s parent (or, for font-size itself, to the parent’s computed size). rem is relative to the font size of the root <html> element, no matter how deeply nested the element using it is. Picking the right one is less about syntax and more about which one keeps a design predictable as it scales, nests, and responds to user preferences.
px: fixed and absolute
A pixel value never changes based on context. 16px is 16px whether it’s on a top-level heading or nested five levels deep inside other elements:
.card-title {
font-size: 16px;
}
This predictability is also px’s weakness for typography: it doesn’t scale when a user changes their browser’s default font size in accessibility settings. Someone who bumps their base font size up to make text more readable sees no difference on elements sized in px, because the unit is deliberately absolute. That makes px a reasonable choice for things that genuinely shouldn’t scale with text — a 1px border, a fixed icon size — but a poor default for font sizes, where respecting user preference matters. See web accessibility basics for more on why respecting user-controlled settings like this matters.
em: relative to the parent
An em value is computed relative to the font size of the element’s parent. 1em means “the same as the parent’s font size”; 1.5em means “one and a half times the parent’s font size”:
.parent {
font-size: 20px;
}
.child {
font-size: 1.5em; /* computes to 30px */
}
The catch is that em compounds when nested. If a .child containing another element sized in em sits inside that 30px parent, the grandchild’s em is now relative to 30px, not the original 20px. Nest several em-sized elements inside each other and font sizes can balloon or shrink unpredictably, since each level multiplies against the level above it rather than a single fixed reference.
This compounding isn’t always a bug — it can be genuinely useful for component-relative sizing, like padding or icon size that should scale proportionally with whatever font size a component happens to render at, regardless of where it’s placed. But it’s a common source of confusing, hard-to-trace font-size bugs when used broadly across a nested layout.
rem: relative to the root
rem stands for “root em.” It behaves exactly like em, except it’s always relative to the root <html> element’s font size — not the immediate parent — no matter how deeply the element sizing itself is nested:
html {
font-size: 16px;
}
.deeply-nested-element {
font-size: 1.25rem; /* always 20px, regardless of nesting */
}
Because there’s only one reference point (the root), rem avoids the compounding problem entirely. This is why rem has become the default recommendation for most font sizing in modern CSS: it scales cleanly with a user’s browser font-size preference (since that preference changes the root’s computed size), and it stays predictable no matter how deeply an element is nested in the DOM.
Comparing the three
| px | em | rem | |
|---|---|---|---|
| Relative to | Nothing — fixed | Parent element’s font size | Root <html> font size |
| Compounds when nested | No | Yes | No |
| Scales with user font-size preference | No | Yes | Yes |
| Best for | Borders, fixed icons, things that shouldn’t scale | Component-internal proportional sizing | Font sizes, spacing that should respect user preferences |
| Predictability | High (but inflexible) | Low in deep nesting | High |
A practical approach
A common, low-friction convention: use rem for font sizes and most spacing (margin, padding, gaps) so everything scales together and respects the user’s font-size preference. Reserve em for cases where you deliberately want sizing relative to a component’s own font size — say, an icon that should always be sized proportionally to the text next to it, regardless of what that text’s size happens to be at any given breakpoint. Use px sparingly, for things that are genuinely meant to be fixed regardless of typography, like a 1px hairline border.
This pairs naturally with CSS custom properties: defining spacing and type scales as rem-based custom properties on the root gives you a single source of truth that every component can reference, and adjusting the root font size (or letting the user’s browser do it) cascades consistently through the whole design.
Where this fits with responsive design
rem and em also interact with newer layout primitives. CSS container queries let a component respond to the size of its container rather than the viewport, and pairing that with rem-based typography keeps text proportions consistent even as a component’s layout adapts. Similarly, logical properties and relative units both aim at the same underlying goal: styles that adapt gracefully to context — writing direction in one case, user and container sizing in the other — rather than being hardcoded to a single fixed assumption.
The takeaway
px is fixed and predictable but ignores user font-size preferences; em scales with a parent’s font size but compounds awkwardly when nested; rem scales with the root font size and avoids compounding, which is why it’s the standard default for typography and spacing in modern CSS. Use rem broadly, reach for em when you want sizing relative to a component’s own font size, and keep px for the rare cases — borders, fixed icons — that should never scale at all.
Tagged
Keep reading
Takina · · 4 min read CSS object-fit and object-position, Explained
object-fit controls how an image or video is cropped inside its box, and object-position controls which part of it stays visible. How they work together.
Takina · · 5 min read CSS inherit, initial, unset & revert Explained
CSS's four global keywords control where a property's value comes from. How inherit, initial, unset, and revert differ, with a comparison table.
Takina · · 4 min read Dynamic Viewport Units: dvh, svh, and lvh Explained
dvh, svh, and lvh fix the classic mobile vh bug where browser toolbars cut off full-height layouts. Here's what each unit measures and when to use it.