Skip to content

CSS & layout

PX to EM converter

Pixels to em and back, plus the compounding behaviour that makes em bite.

px
em
px
Click to copy.

em is relative to the parent element's computed font size, not the root — so it compounds through nesting. Set the basis to whatever the parent actually resolves to.

Reference table

Pixel values converted to em
Pixels em
1px 0.0625em
2px 0.125em
4px 0.25em
6px 0.375em
8px 0.5em
10px 0.625em
11px 0.6875em
12px 0.75em
13px 0.8125em
14px 0.875em
15px 0.9375em
16px 1em
18px 1.125em
20px 1.25em
22px 1.375em
24px 1.5em
26px 1.625em
28px 1.75em
30px 1.875em
32px 2em
36px 2.25em
40px 2.5em
44px 2.75em
48px 3em
56px 3.5em
64px 4em
72px 4.5em
80px 5em
96px 6em
112px 7em
128px 8em
160px 10em
192px 12em
256px 16em

The arithmetic is identical to rem. What you divide by isn’t, and that changes everything about how the unit behaves.

What em measures against

em resolves against the computed font size of the parent element, not the root. 1.5em means “one and a half times whatever my parent turned out to be”, and the answer moves depending on where the element sits in the tree.

Parent at the 16px default? 1.5em is 24px. Parent at 20px? The same declaration is now 30px. Nothing in your CSS changed; the context did.

Put the parent’s real computed size into the basis field above. If you leave it at 16 out of habit you’ll get the rem answer wearing an em label.

The compounding trap

This is the behaviour that makes people swear off em entirely, and it’s worth seeing rather than being told about:

.card { font-size: 0.9em; }
HTML
<div class="card">          <!-- 16 × 0.9  = 14.4px -->
  <div class="card">        <!-- 14.4 × 0.9 = 12.96px -->
    <div class="card">      <!-- 12.96 × 0.9 = 11.66px -->
      Why is this so small?

Every level multiplies again. Three levels of a completely reasonable 0.9em and the text is 27% smaller than anyone intended. In rem all three would be the same size, because rem never looks up the tree.

It isn’t a bug to be worked around. It’s the defining property of the unit, and now and then it’s precisely what you want.

When em is the better choice

Padding and spacing that should track the element’s own text is the strongest case. A button with 0.75em 1.5em padding keeps its proportions whether it’s the small variant or the large one: set the font size and the padding follows. Do that in rem and you’re re-specifying padding at every size.

The same logic covers most component-internal spacing, anything that should scale as a unit when one font size changes. letter-spacing and text-indent too, since those are almost always meant to be proportional to the text they sit on.

For layout, page-level spacing, container widths and design-system font sizes, reach for rem instead. You want one predictable answer there regardless of nesting.

Most codebases settle on some version of rem for the page, em inside the component, and that’s a fine rule to start from.

The media query exception

Both units resolve against the browser’s default font size inside a @media rule, ignoring whatever you set on html. They’re interchangeable there. Anyone who has set 62.5% and expected their breakpoints to shift has run into this.

A note on finding the parent size

Devtools, Computed panel, font-size. Use that number, not whatever the parent’s CSS declaration says, because the parent may well be sized in em itself and you’d be starting the compounding problem one level early.

Published