Skip to content
Menu

px, rem and em in CSS: when to use each

Three length units, three different reference points. What each one is measured against, how they behave when a reader changes their font size, and a simple rule for choosing.

Last updated

Every CSS length is measured against something. For px it’s a fixed reference, for rem it’s the root font size, and for em it’s the font size of the element itself. Most of the confusion about which to use comes from not knowing which of those three is in play.

px: a fixed reference length

A CSS pixel is not a hardware pixel. The CSS specification defines it as 1/96 of an inch, so 96 px = 1 in, and on a high-density phone screen one CSS pixel may cover three or more physical pixels. What matters for layout is that px never changes with font settings: a 320px column is 320px whether the reader has asked for larger text or not.

That makes px a good fit for things that should stay put: borders, hairline rules, shadows, small icons, and media that has a natural pixel size.

rem: relative to the root font size

rem means “root em”: a multiple of the font size on the html element. Browsers set that to 16px by default, so out of the box:

  • 1rem is 16px
  • 0.875rem is 14px
  • 1.5rem is 24px
  • 2rem is 32px

To convert, divide pixels by the root size: 24 ÷ 16 = 1.5rem. The px to rem converter does this for any root size, and rem to px goes back.

The reason rem matters is that the root size isn’t always 16px. Every major browser lets readers choose a default font size in its settings, and people with low vision often set it to 20px or more. If your type is in rem, it grows with that setting. If it’s in px, it doesn’t.

em: relative to the current element

em is a multiple of the element’s own font size (or, when setting font-size itself, of the parent’s font size). That makes it context-dependent, which is both its strength and its trap.

The strength: spacing that scales with its text. Give a button padding: 0.5em 1em and its padding stays in proportion whether the button’s text is 14px or 20px. The same goes for icon sizes next to text, and for the gap under a heading.

The trap: em compounds. Suppose a list sets font-size: 0.875em and contains a nested list with the same rule:

  • The outer list’s text is 0.875 × 16 = 14px.
  • The nested list’s text is 0.875 × 14 = 12.25px.
  • A third level would be 0.875 × 12.25 = 10.71875px.

Nothing in the stylesheet says 12.25px, yet that’s what the reader gets. With rem the nested lists would all stay at 14px. The px to em and em to px converters let you set the parent size, so you can check what a nested value really comes to.

The zoom test

Two different things happen when someone enlarges a page:

  • Browser zoom (Ctrl or Cmd and +) scales everything, px included. Layouts in any unit survive it reasonably well.
  • The default font size setting changes only the root font size. Text in rem and em grows; text in px stays the same size.

The second case is the one that separates the units. WCAG success criterion 1.4.4 asks that text can be resized to 200% without loss of content or function, and a font size setting is one of the ways people do that. Type sized in rem passes this test without any extra work.

The 62.5% trick and its costs

Converting by 16 is awkward, so a common shortcut sets the root to 62.5%:

  • html { font-size: 62.5%; } makes the root 10px (62.5% of 16px), so 1.4rem is 14px and 2.4rem is 24px.

Because it’s a percentage, it still respects the reader’s setting: with a 20px default, the root becomes 12.5px. The costs are elsewhere:

  • Third-party components assume 16px. A date picker or embed styled with 1rem text suddenly renders at 10px.
  • You must reset body text. Without body { font-size: 1.6rem; }, any text you forget to size is 10px.
  • It only helps mental math. Modern tools and converters do the division for you.

Never set the root in pixels (html { font-size: 10px; }). That overrides the reader’s choice entirely.

Fluid type: vw with a rem floor

Viewport units (vw, vh) size things relative to the browser window: 1vw is 1% of the viewport width. They’re useful for headings that should grow on wide screens, but text sized only in vw barely responds to zoom, because zooming in also shrinks the viewport measured in CSS pixels.

The usual fix is to mix in rem and clamp the range:

  • font-size: clamp(1.5rem, 1rem + 2vw, 3rem);

The rem part keeps the text responsive to font settings and zoom, the vw part adds fluid growth, and clamp keeps it between sensible limits. The px to vw converter helps when a design file gives you a pixel size at a particular viewport width.

Media queries use em, but not your em

Inside a media query, em and rem are relative to the browser’s initial font size, not to anything you set on html. So @media (min-width: 40em) means 640px at the default setting, and switches later for a reader who has raised their default font size. That’s usually what you want: the layout changes when the text no longer fits, rather than at a fixed window width.

Line height without units

Line height is the one place where no unit is often best. A unitless line-height: 1.5 multiplies each element’s own font size, so a 16px paragraph gets 24px lines and a 32px heading gets 48px lines. A value like line-height: 24px (or 1.5rem) is inherited as a fixed length, which makes large headings collide. The line height calculator converts between unitless, px and rem values.

A simple rule

  • rem for font sizes, so type follows the reader’s settings.
  • em for spacing that belongs to text: button padding, icon sizes, gaps next to headings.
  • px for things that shouldn’t scale: borders, rules, shadows, fixed-size media.
  • Unitless numbers for line height.
  • clamp() with rem and vw for fluid headings.

When a design comes to you in pixels, convert the type to rem at the 16px root the design assumed, and check nested em values before shipping. The font size converter shows a size in px, rem, em, pt and mm side by side.

Tools in this guide

Sources

How we check values · Report a problem with this page