Most developers reach for px by default — it feels precise, predictable, and familiar. But for font sizes, px has a significant accessibility problem: it ignores the user's browser font size preference. Users who have set their browser default to 20px because they need larger text will see your 16px font at exactly 16px regardless. That's a real failure for real users.
The DevToolShack px ↔ rem Converter converts between the two units instantly — handy when working with designs specified in pixels that need to be implemented in rem.
What Each Unit Actually Means
px (pixels)
A CSS pixel is an absolute unit. font-size: 16px renders at 16 CSS pixels regardless of what the user has set as their browser default font size. On high-DPI screens, browsers scale CSS pixels — so 16px might be 32 physical pixels — but the key point is that user preferences have no effect.
rem (root em)
rem is relative to the font size of the root element (<html>). The browser default is 16px, so 1rem = 16px by default. But if the user has changed their browser default to 20px, then 1rem = 20px, and your text scales accordingly. This is exactly what accessibility-conscious design requires.
em
em is relative to the font size of the current element's parent. This makes it useful for component-level scaling but dangerous for nesting — if you have a list inside a section inside a div, all using em, the font sizes compound multiplicatively. rem avoids this by always being relative to the root, not the parent.
The Conversion
The math is simple when the root font size is 16px (the default):
rem = px ÷ 16
16px = 1rem
12px = 0.75rem
14px = 0.875rem
18px = 1.125rem
20px = 1.25rem
24px = 1.5rem
32px = 2rem
48px = 3rem
Use the px ↔ rem Converter for any value that doesn't divide neatly — or when the root font size is something other than 16px.
The 62.5% Trick
Many developers find rem math annoying (14px ÷ 16 = 0.875rem isn't intuitive). A common trick is to set the root font size to 62.5%:
html {
font-size: 62.5%; /* 10px equivalent at default browser settings */
}
body {
font-size: 1.6rem; /* 16px */
}
h1 { font-size: 3.2rem; } /* 32px */
p { font-size: 1.4rem; } /* 14px */
Now 1rem = 10px, making the mental arithmetic easy. The critical point: you're setting the root to 62.5%, not 10px — so if the user's browser default is 20px, 1rem = 12.5px and everything scales correctly. Never set html { font-size: 10px; } — that overrides user preferences just like px does.
html { font-size: 10px; } defeats the entire purpose of using rem — it creates a fixed baseline that ignores user preferences. Always use a percentage if you want to change the base: 62.5%, 100%, etc.When to Use Each Unit
| Property | Recommended Unit | Reason |
|---|---|---|
| Font size | rem | Respects user preferences |
| Line height | Unitless (e.g. 1.6) | Scales with font size automatically |
| Spacing (margin, padding) | rem or px | rem scales with text; px stays fixed |
| Border widths | px | 1px borders shouldn't scale |
| Media query breakpoints | em or rem | px-based breakpoints don't respond to zoom |
| Component-level relative sizing | em | Scales relative to component's own font size |
| Layout widths | px, %, or ch | Depends on design intent |
Media Queries: Use em or rem, Not px
Browser zoom increases the pixel density — a user who zooms to 150% is effectively changing their viewport. Media queries written in px don't respond to zoom correctly; em-based queries do:
/* ❌ Doesn't respond correctly to browser zoom */
@media (min-width: 768px) { ... }
/* ✅ Works correctly at all zoom levels */
@media (min-width: 48em) { ... } /* 48 × 16 = 768px at default */