# px, rem, and em in CSS: When to Use Each

CSS gives you three everyday length units that look interchangeable and behave very differently: `px`, `rem`, and `em`. Pick the wrong one and your layout either ignores a user's font-size preference or balloons unexpectedly inside nested components. Here's how to choose.

## px — absolute and predictable

A pixel is a fixed reference size. `16px` is `16px` no matter where it appears. That predictability is the appeal and the problem: text set in `px` does **not** respond when a user increases their browser's default font size for readability. For that reason, prefer to avoid `px` for font sizes. It's perfectly fine for things that genuinely shouldn't scale — `1px` borders, fixed icon sizes, hairline rules.

## rem — relative to the root

`rem` means "relative to the **root** element's font size." By default browsers use `16px`, so:

```
1rem  = 16px
1.5rem = 24px
0.5rem = 8px
```

The magic is that the user controls the root. If someone sets their browser font size to 20px, every `rem` on the page scales with it — `1rem` becomes `20px`, your headings, spacing, and body text all grow together. This is why `rem` is the default choice for **font sizes and most spacing** in accessible, responsive design.

Because `rem` always references the root, it never compounds. `1rem` is the same everywhere, regardless of nesting.

To convert a design spec from px to rem (or back), the [PX ↔ REM converter](/convert/px-to-rem) does the math at any root size.

## em — relative to the element

`em` is relative to the **current element's** font size. If a button has `font-size: 18px`, then `padding: 1em` is `18px`; if the button's font size changes to `14px`, the same `1em` padding becomes `14px`. That's powerful: `em` lets a component's internal spacing scale with its own text.

The catch is **compounding**. Because `em` references the *element's* font size, and font sizes inherit, nested `em`-based font sizes multiply:

```html
<ul style="font-size: 1.2em">      <!-- 1.2 × parent -->
  <li>
    <ul style="font-size: 1.2em">   <!-- 1.2 × 1.2 = 1.44 × grandparent -->
      <li>This text is bigger than you expected</li>
    </ul>
  </li>
</ul>
```

Each level multiplies the last. This compounding is the single most common source of "why is this text huge?" bugs.

## A simple decision guide

- **Font sizes** → `rem`. Predictable, respects user preference, no compounding.
- **Component-local spacing that should scale with the component's text** (button padding, badge gaps) → `em`.
- **Things that must not scale** (borders, fixed hairlines) → `px`.
- **Media query breakpoints** → `em` or `rem` (they respect zoom better than `px`).

## The 62.5% trick — and why to skip it

You'll see advice to set `html { font-size: 62.5% }` so that `1rem = 10px` and the math is easier. It works, but it overrides the user's chosen base size, quietly undoing the accessibility benefit of `rem` in the first place. Better to keep the root at its default and let a converter handle the arithmetic.

If you're translating a whole stylesheet between units, the [CSS unit converters](/convert) cover px↔rem, px↔em, and rem↔em with a configurable base. Default to `rem`, reach for `em` when a value should track its own element, and keep `px` for the few things that should never move.
