Blog
3 min read

rem vs em vs px in CSS: Which Unit Should You Use?

px is fixed, rem is relative to the root font size, em is relative to the current element's font size. What each unit means, why rem is the safe default for font sizes and spacing, where em and px still make sense, and when to reach for %, vw, vh and dvh.

CSS has a lot of units. Three cover most sizing decisions: px, rem and em. The short answer:

Use rem for font sizes and spacing, px for thin details like borders, and em when something should scale with its own text.

px — pixels

.card { padding: 16px; border: 1px solid #ddd; }

A CSS pixel is a fixed size (not necessarily one physical screen pixel — high-resolution screens use several). It doesn't change based on anything else on the page.

Problem: if a user increases their browser's default font size for readability, text set in px doesn't grow. That's an accessibility issue. (Web accessibility basics)

rem — relative to the root

h1 { font-size: 2rem; }    /* 2 × root font size */
.card { padding: 1rem; }   /* 1 × root font size */

rem means "root em": a multiple of the font size on the <html> element. Browsers default that to 16px, so 1rem = 16px, 1.5rem = 24px, 0.875rem = 14px.

Why it's the safe default: if a user sets their browser to larger text, everything in rem scales with it, proportionally. And it's predictable — 1rem is the same everywhere on the page.

Tailwind CSS uses rem for its spacing and type scale for this reason. (What is Tailwind CSS?)

em — relative to the current font size

.button { font-size: 1.125rem; padding: 0.5em 1em; }

em is a multiple of the current element's font size. Here the padding scales with the button's text: make the text bigger and the padding grows to match. That's exactly what you want for buttons, badges and icons next to text.

The catch: em compounds. Used for font sizes in nested elements, it multiplies:

li { font-size: 1.2em; }

A list inside a list inside a list gets 1.2 × 1.2 × 1.2 = 1.73 times bigger. This is why rem replaced em for most font sizes.

Side by side

Unit Relative to Good for
px Nothing (fixed) Borders, hairlines, shadows, fine details
rem Root (<html>) font size Font sizes, spacing, layout widths
em The element's own font size Padding/margins that scale with text, icons
% The parent element (usually) Widths inside a container
vw / vh Viewport width / height Full-screen sections, fluid type
dvh Visible viewport height on mobile Full-height layouts on phones
ch Width of the "0" character Readable line lengths (max-width: 65ch)

The other units worth knowing

  • % — width: 50% is half the parent's width.
  • vw / vh — 100vh is the full height of the browser window. On phones, 100vh can be taller than the visible area because of the address bar; 100dvh (dynamic viewport height) fixes that. (Responsive design basics)
  • clamp() — not a unit, but useful: font-size: clamp(1.5rem, 4vw, 3rem) grows with the screen but stays within a minimum and maximum.

The old "62.5%" trick

Some code sets html { font-size: 62.5%; } so that 1rem = 10px for easier maths. It works, but it overrides the user's preferred base size in a confusing way and fights with libraries that assume 16px. Modern advice: leave the root alone and think in rem directly.

A sensible setup

body { font-size: 1rem; line-height: 1.5; }
h1 { font-size: clamp(2rem, 5vw, 3rem); }
.container { max-width: 70rem; padding-inline: 1rem; }
.prose { max-width: 65ch; }
.card { border: 1px solid var(--border); border-radius: 0.5rem; }
.button { padding: 0.5em 1em; }

(For the layout itself, see Flexbox vs Grid.)


EasySpawn hosts your site on a fast server with HTTPS, and Claude Code can tidy your CSS units for you while you watch the result live. See how it works or join the waitlist.

Related: Responsive Design Basics · Flexbox vs Grid · CSS Position Explained · Web Accessibility Basics

Keep reading