px vs rem vs em: what each unit is relative to, and which to use where

Three units, one argument: should a button's padding be 12px, 0.75rem or 0.75em? The answer depends on what should happen when the user enlarges their browser's default text โ€” which many people do โ€” and on what each unit is measured against. The px to rem converter does the arithmetic; this guide settles the choice.

What a pixel is (it isn't a pixel)

A CSS pixel is not a hardware pixel. It is defined as 1/96 of an inch at arm's length โ€” a reference size โ€” and the browser maps it to device pixels using the device's pixel ratio: 1 CSS px is 2ร—2 device pixels on a 2ร— "retina" screen, 3ร—3 on many phones. So 16px text is the same physical size on any device regardless of resolution, and that consistency is why px remains useful for things that shouldn't scale with text: borders, shadows, hairlines, image dimensions. What px does not do is respond to the user's font-size preference in browser settings, which is where the argument starts.

rem: relative to the root

1rem equals the font size of the root element (html), which by default is the browser's setting โ€” 16px unless the user has changed it. 1.5rem is 24px at default and 30px for a user who set 20px. Everything sized in rem scales together with that preference: text, spacing, container widths, breakpoints. That is the accessibility argument for rem, and it is why 16px = 1rem is the conversion everyone remembers (and why 0.875rem is 14px, 1.125rem 18px, 0.5rem 8px). A common trick โ€” setting html { font-size: 62.5% } so 1rem is 10px โ€” makes the maths easier and still respects the user's setting proportionally.

em: relative to the parent, and why it compounds

1em equals the font size of the element itself (for font-size, its parent's). Nest three elements each at 1.2em and the innermost text is 1.2ยณ = 1.73 times the base โ€” compounding that surprises everyone once. That same behaviour is a feature inside a component: padding of 0.75em on a button scales with the button's own font size, so a small button and a large button keep their proportions without extra rules. em is for spacing that belongs to the text it surrounds โ€” padding, letter-spacing, icon sizes beside text โ€” and for media queries in older code.

Which unit where

  • Font sizes: rem. Never px, which ignores the user's preference.
  • Layout spacing, margins, max-widths, grid gaps: rem, so the whole layout scales with text.
  • Padding and spacing inside a component: em, to scale with that component's text.
  • Borders, outlines, shadows, hairlines: px. A 1px border should stay 1px.
  • Media queries: em or rem (they respond to zoom and font settings consistently across browsers); px is common and slightly worse.
  • Images and icons: px or rem depending on whether they should grow with text; SVG icons beside text in em.

Viewport, percentage and the rest

vw and vh are percentages of the viewport width and height โ€” for full-bleed sections and fluid type (with clamp() to keep it sane), with the caveat that 100vh misbehaves on mobile browsers whose toolbars come and go (dvh fixes it). Percentages are relative to the parent's corresponding dimension โ€” fine for widths, confusing for heights. ch is the width of a "0", handy for line lengths (65ch is a readable paragraph). Absolute units (in, cm, pt) are for print stylesheets only. The box shadow generator and gradient generator output px because that's what those properties want; the flexbox playground shows how the units interact in a layout, and Flexbox vs Grid: which one, when covers the layout side.

Sources and further reading

The claims in this guide rest on these references, which were checked when the guide was last updated. Spotted an error? The contact page says how to report it.

  1. CSS length units โ€” MDN Web Docs

Try the tool

Frequently asked questions

How many px is 1 rem?

16 px at the browser default. It scales with the user's font-size setting: at 20 px, 1 rem is 20 px. The converter assumes 16 unless you change the base.

Should I use rem or em for font size?

rem โ€” it scales with the user's preference without compounding through nested elements. Use em for spacing inside a component that should follow that component's text size.

Is px bad for accessibility?

For font sizes, yes: px ignores the user's default-text-size setting (zoom still works). For borders and shadows, px is correct.

Why does my nested text keep getting bigger?

em compounds: each level multiplies its parent's size. Switch the font sizes to rem, which always references the root.