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
| Factor | px | rem |
|---|---|---|
| Scales with browser font-size pref | No | Yes |
| Scales with page zoom | Yes | Yes |
| Predictable across nesting | Yes | Yes (unlike em) |
| WCAG 1.4.4 compliant | Via zoom only | Via both mechanisms |
| Design handoff is intuitive | Yes (matches Figma) | Requires conversion |
| Token-system friendly | No | Yes |
| Performance | Identical | Identical |
| Browser support | Universal | Universal |
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:
- 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.
- Annotate with tokens, not raw px. Instead of
font-size: 24px, annotatefont-size: --text-xl (1.5rem / 24px). - Use the conversion tool for spot checks. Paste pixel values into the PX to REM converter to verify token alignment.
- 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.