🛠️DevKitPack
Back to blog
Dev Tools5 min read

PX vs REM: A Front-End Developer's Guide to Sizing

Pixels feel precise and certain, which is exactly why they quietly break accessibility and responsive scaling. Here is when to reach for rem, how the conversion works, and the habits that keep a UI flexible.

Pixels are the unit every developer reaches for first, because a pixel feels concrete: 16px is 16px, no ambiguity. That certainty is comforting, and it is also the trap. A layout built entirely in pixels is rigid in ways you do not notice until a user changes their browser's font size and your carefully sized text refuses to budge. Understanding when to use px and when to use rem is one of the small skills that separates fragile CSS from flexible CSS.

What px and rem actually are

A pixel in CSS is an absolute unit. It is a fixed reference size that does not respond to anything the user has configured; 16px renders at the same intended size regardless of preferences. That predictability is its appeal and its weakness — it ignores the user's expressed wishes by design.

A rem, by contrast, is relative: it means "this many times the root font size." If the root is the default 16px, then 1rem equals 16px and 1.5rem equals 24px. The crucial difference is the word relative. When the root font size changes — because the user increased it, or because you adjusted it at a breakpoint — everything sized in rem rescales in proportion, automatically.

The accessibility problem with pixels

Browsers let users set a preferred default font size, and many people rely on it — for low vision, for comfort, for reading on a distant screen. When you set font sizes in pixels, you override that preference entirely. The user asks for larger text; your pixel-locked layout politely refuses. It is one of the most common and least visible accessibility failures on the web.

/* Ignores the user's font-size preference */
.body-text { font-size: 16px; }

/* Respects it — scales with the root */
.body-text { font-size: 1rem; }

Sizing text in rem fixes this with no extra effort. Because the root font size honors the user's setting, rem-based text grows and shrinks with it. The same page becomes usable for someone who needs 150% text and someone who prefers it small, from a single set of styles.

How the math works

The conversion is simple once the base is fixed. With the conventional 16px root, divide pixels by 16 to get rem, and multiply rem by 16 to get pixels. 24px is 1.5rem; 12px is 0.75rem; 40px is 2.5rem. That is the entire formula, and it is why a small converter is a handy thing to keep within reach when you are translating a pixel-based design into flexible styles.

/* rem = px / root-size */
1rem   = 16px
1.5rem = 24px
0.75rem = 12px

/* A common trick: set root to make the math 10x easier */
:root { font-size: 62.5%; }  /* now 1rem = 10px, 1.6rem = 16px */

The 62.5% trick rebases the root so that 1rem equals 10px, turning every conversion into a decimal shift. It is convenient but controversial, because it can interact awkwardly with components that assume a 16px root. Most teams skip it and simply keep a converter handy, which costs nothing and avoids the surprises.

When to use which

The rule of thumb is to use rem for anything that should scale with the user's text preferences, and reserve pixels for the rare things that genuinely should not. That makes most of your CSS rem and a small, deliberate set of values px.

  • Use rem for font sizes, spacing, and most layout dimensions — anything tied to readable text.
  • Use px for hairline borders (1px), where scaling would blur or double the line.
  • Use px for fine, fixed details like a 1px divider or a precise icon stroke.
  • When in doubt, prefer rem — flexible-by-default is the safer mistake to make.
Pixels promise control. Rem gives the control back to the person actually reading your page.

A practical workflow

Designs usually arrive in pixels, because design tools think in pixels. The job is to translate as you build rather than copying the numbers in raw. Keep a converter open, set your base, and convert each value as you write it — font sizes and spacing become rem, the genuine exceptions stay px. After a week the common conversions live in your head and the habit costs nothing.

Define your spacing and type scales in rem from the start, so flexibility is the default rather than a retrofit. The expensive version of this lesson is converting a large pixel-based codebase to rem after an accessibility audit; the cheap version is simply starting in rem and never paying that bill.

A word on em

There is a third unit, em, that is relative to the font size of the current element rather than the root. It is powerful for components that should scale as a self-contained unit — pad a button in em and its padding grows with its own text — but it compounds when elements nest, which makes it harder to reason about across a whole layout. Rem avoids that compounding by always referring to the single root, which is why it is the safer default for global sizing.

The takeaway

Reach for rem by default, drop to px only for the small fixed details that truly need it, and keep the conversion within reach while the habit forms. The reward is a UI that honors the people using it — text that grows when they ask, layouts that flex instead of fighting back — built from the same effort you were already spending, just pointed at a more forgiving unit.

Related posts