Skip to main content

Published 2026-02-02 · 3 min read

By Akash Yadav · Frontend Engineer

PX vs REM: Which Should You Use?

PX is measurable; REM respects user scaling. Here is a nuanced decision framework for beginners and design-system stewards alike.

The core difference

px is an absolute unit — it describes a number of device-independent pixels that does not change based on the surrounding context. A font-size: 16px is 16px whether the user has changed their browser default, whether the element is nested, or whether the viewport is 320px or 4K wide.

rem is a relative unit — it multiplies the computed font-size of the html element. At the browser default of 16px, 1rem = 16px. But if a user has set their browser default to 20px, 1rem = 20px. If the root is set to 112.5% of the browser default, 1rem inherits that ratio.

The practical consequence: rem values are user-adjustable, px values are not.

Practical defaults: when to use each

Use REM for:

/* Typography — respects user preference scaling */
h1        { font-size: 2.5rem;  }
h2        { font-size: 2rem;    }
h3        { font-size: 1.5rem;  }
body      { font-size: 1rem;    }
small     { font-size: 0.875rem;}

/* Spacing — scales with type for visual harmony */
.card     { padding: 1.5rem;    }
.section  { gap: 2rem;          }
.form-row { margin-bottom: 1rem;}

/* Border-radius tied to type scale */
.button   { border-radius: 0.375rem; }

Use px for:

/* Hairlines and precise borders */
.divider         { border-top: 1px solid; }
.input           { border: 1px solid;     }
.focus-ring      { outline: 2px solid;    }
.focus-ring      { outline-offset: 2px;   }

/* Shadow blur/spread where exact pixel spread matters */
.card { box-shadow: 0 1px 3px rgba(0,0,0,0.12), 0 1px 2px rgba(0,0,0,0.24); }

/* Icon dimensions for pixel-grid alignment */
.icon-sm { width: 16px; height: 16px; }
.icon-md { width: 20px; height: 20px; }

Side-by-side comparison

Factorpxrem
Scales with browser font-size prefNoYes
Scales with page zoomYesYes
Predictable across nestingYesYes (unlike em)
WCAG 1.4.4 compliantVia zoom onlyVia both mechanisms
Design handoff is intuitiveYes (matches Figma)Requires conversion
Token-system friendlyNoYes
PerformanceIdenticalIdentical
Browser supportUniversalUniversal

Designer handoff workflow

Design tools (Figma, Sketch, Framer) output absolute pixel values. The design-to-code handoff creates a natural px-to-rem translation point.

A practical workflow:

  1. Establish root size in the design file. Add a root font-size annotation at the top of your Figma file: "Root font-size: 16px". This removes ambiguity for developers.
  2. Annotate with tokens, not raw px. Instead of font-size: 24px, annotate font-size: --text-xl (1.5rem / 24px).
  3. Use the conversion tool for spot checks. Paste pixel values into the PX to REM converter to verify token alignment.
  4. Document the assumed root in code. A comment in your tokens file prevents silent drift:
/* Token values assume html { font-size: 16px } = 100% browser default */
:root {
  --text-xl: 1.5rem;  /* 24px at 16px root */
  --space-6: 1.5rem;  /* 24px at 16px root */
}

Explore EM when padding should feel "attached" to nearby type — PX to EM preserves the mathematics for local rhythm.

Migrating px to rem

If you have an existing codebase in px, a systematic migration is better than opportunistic conversion:

Step 1: Inventory your px values

# Find all font-size px declarations
grep -r "font-size:.*px" src/ --include="*.css"

# Find all padding/margin px declarations
grep -r "padding:.*px|margin:.*px" src/ --include="*.css"

Step 2: Decide which to convert

  • Typography: convert all to rem
  • Spacing/padding: convert to rem (skip 1px borders)
  • Borders and hairlines: keep as px

Step 3: Convert in batches using tooling

For CSS/SCSS projects, postcss-pxtorem automates conversion with configurable exclusion patterns:

// postcss.config.js
module.exports = {
  plugins: {
    'postcss-pxtorem': {
      rootValue: 16,
      propList: ['font-size', 'line-height', 'padding', 'margin', 'gap'],
      selectorBlackList: ['.no-rem'] // opt-out for specific selectors
    }
  }
}

Step 4: Spot check with the converter

Use REM to PX to verify that converted values match your intended pixel output at the assumed root size.

The 62.5% root-size hack

A common legacy pattern:

/* The "62.5% trick" — do not copy this */
html { font-size: 62.5%; } /* sets root to 10px */
body { font-size: 1.6rem; } /* restores to 16px */

/* Now 1.6rem = 16px, 2.4rem = 24px — easier mental math */
h1 { font-size: 3.2rem; } /* 32px */

This pattern makes rem arithmetic easier at the cost of overriding user browser preferences. A user who has set their browser default to 20px gets 62.5% × 20px = 12.5px as the root — causing all values to be smaller than intended.

The correct modern approach: set html { font-size: 100%; } (defer to user preference), use token names or a converter for the maths, and never set a pixel-valued root.

Key takeaways

  • REM is the right default for typography and spacing in any project that values accessibility.
  • px is legitimate for borders, focus rings, hairlines, and some icon sizing.
  • The 62.5% hack overrides user preferences — do not use it. Use tokens and tools instead.
  • Designer handoff: annotate Figma with token names + px equivalents; document the assumed root in code.
  • Migration: convert typography and spacing to rem first; leave borders in px.

Continue your reading with Modern CSS units guide for 2026 once the REM habit sticks.

Frequently asked questions

Can a marketing site stay in px?
Briefs may be delivered in px, but production code should converge on REM tokens. Convert intentionally with a tool, not implicitly by copying pixel values from a design file.
Is it okay to mix px and rem in the same file?
Yes, intentional mixing is fine. REM for typography and spacing, px for borders and hairlines is a common and correct pattern. The problem is accidental mixing — px values that appear simply because they were copied from design tools without conversion.
What is the fastest way to convert a large px codebase to rem?
Use the PX to REM converter for manual checks, and a code-mod tool (like postcss-pxtorem) for bulk conversion. Always set your root size explicitly in the code-mod config so conversions are deterministic.
My designer uses px in Figma. How do I communicate token values?
Add a token annotation layer in Figma showing both the px value and the REM/token equivalent. Once the team has memorised the token names, designers can spec by token name and developers can apply them directly.
Does Google rank REM sites higher than px sites?
Google does not use CSS unit choices as a ranking signal. The SEO benefit of REM comes indirectly: accessible text scaling reduces bounce rates from users with accessibility needs, and Core Web Vitals (especially CLS) can be improved by layouts that scale proportionally.
Are there performance differences between px and rem?
No meaningful difference. Both are resolved to computed pixel values before painting. The cascade cost is identical.