px vs rem vs em in CSS: Which Unit to Use for What
px is fixed. rem is relative to root font size. em is relative to parent. Use rem for sizing, em for padding that scales with text, and px for borders. Full rules.
The short answer
Use rem for font sizes and layout dimensions that should respect user preferences. Use em for padding, margin, and border-radius that should scale with the element's own font size. Use px for borders, box-shadows, and rare hairline details that must stay exactly that size.
Side-by-side
| Unit | Anchored to | User-zoom-respecting | Best for |
|---|---|---|---|
| px | Device pixel (roughly) | Yes (browser zoom scales) | Borders, shadows, fixed details |
| em | Parent element's font-size | Yes | Padding/margin within a component |
| rem | Root <html> font-size | Yes, including user prefs | Fonts, layout, almost everything |
| % | Parent (context-dependent) | Yes | Widths within containers |
| vh/vw | Viewport height/width | Yes | Full-screen sections, aspect ratios |
| ch | Width of "0" in current font | Yes | Measure-based typography |
The accessibility argument for rem
Users can change their browser's default font size (Settings → Fonts). This is one of the most common accessibility adjustments — older adults, low-vision users, and anyone with a small laptop screen. When you size text in px, that user preference is ignored. When you size text in rem, everything scales together. This is the primary reason to prefer rem.
When em still makes sense
em is useful when you want something to scale relative to its component's text, not the whole page. Example: a button has padding proportional to its font-size. If you make the button bigger by changing its font-size, you want the padding to grow too. Using padding: 0.5em 1em does exactly that. Using padding: 0.5rem 1rem would leave the padding fixed while the text grows — not what you want for consistent visual proportions.
The nested-em trap
em compounds when nested. If a list has font-size: 1.2em and each <li> also has font-size: 1.2em, items get progressively larger as nesting deepens. This is almost always a bug. rem sidesteps it by always being relative to the root.
The "62.5% trick"
A common pattern: set html { font-size: 62.5%; }. Now 1rem = 10px and you can write font-size: 1.6rem and mean "16px" while still getting rem-based scaling. Purists dislike this because it adds an extra translation layer; pragmatists love it because rem math becomes trivial. Either is fine.
px for borders, always
Hairline borders at 1px look hairline. At 0.0625rem on a user-zoomed page, they can become 0.5px and render as invisible on some monitors. For borders, box-shadow details, and small decoration, stick to px.
The modern default stack
:root {
font-size: 100%; /* respect user preference */
}
body {
font-size: 1rem; /* 16px by default, scales with root */
}
h1 { font-size: 2.25rem; }
h2 { font-size: 1.875rem; }
p { font-size: 1rem; }
.card {
padding: 1.5em; /* scales with card's font-size */
border: 1px solid #ddd; /* stays hairline */
border-radius: 0.5rem; /* respects root */
}
Related CSS tools
Format your stylesheets with CSS formatter. Before shipping, minify with CSS minifier. For picking consistent color values across px/rem-sized components: color converter.
Featured Tools
Try these free related tools directly in your browser — no sign-up required.
CSS Formatter
Beautify and format CSS code with proper indentation and line breaks. Paste minified or messy CSS and get clean, readable output instantly.
CSS Minifier
Minify and compress CSS code instantly online. Remove whitespace, comments, and redundant code to reduce CSS file size and improve page load speed.
Color Converter
Convert colors between HEX, RGB, RGBA, HSL, HSLA, and HSV formats instantly. Pick colors visually and get all format values at once for CSS and design work.