CSS Units: px, em, rem, vw, and When to Use Each
Using the wrong CSS unit causes layouts that break on different screens or ignore user accessibility settings. Here's a practical guide.
px — Absolute
Fixed size. 1px = 1 CSS pixel on standard displays.
.card {
border: 1px solid #ddd; /* ✅ always px */
border-radius: 8px; /* ✅ always px */
box-shadow: 0 2px 8px rgba(0,0,0,0.1); /* ✅ px */
}
Use for: Borders, shadows, fixed icons. Avoid for: Font sizes — px ignores user's browser font preference.
em — Relative to Parent Font Size
Compounds when nested — each child multiplies the parent.
.parent { font-size: 20px; }
.child { font-size: 0.8em; padding: 1em; }
/* child font-size = 16px, padding = 16px */
/* Compounding problem: */
.level-1 { font-size: 1.2em; } /* 19.2px */
.level-2 { font-size: 1.2em; } /* 23px */
.level-3 { font-size: 1.2em; } /* 27.6px — unintended! */
Use for: Component-internal spacing (padding/margin) that should scale with the component's font. Avoid for: Global font sizes.
rem — Relative to Root (Recommended for Typography)
Always relative to html font size. Never compounds.
html { font-size: 16px; } /* browser default */
h1 { font-size: 2rem; } /* 32px */
p { font-size: 1rem; } /* 16px */
.container { max-width: 60rem; } /* 960px */
Accessibility benefit: If user sets browser to 20px, rem-based layouts scale proportionally. px-based layouts ignore this preference.
Use for: Font sizes, global spacing, max-widths — anything that should respect user preferences.
vw / vh — Viewport Units
.hero { min-height: 100vh; }
h1 { font-size: clamp(1.75rem, 4vw, 3rem); } /* fluid scaling */
Mobile vh problem: 100vh includes the browser URL bar. Use modern alternatives:
.hero { height: 100svh; } /* small viewport — stable */
.modal { height: 100dvh; } /* dynamic — updates as URL bar shows/hides */
Use for: Full-bleed sections, modals, fluid typography with clamp().
% — Relative to Parent
.parent { width: 800px; }
.child { width: 50%; } /* 400px */
For height % to work, parent must have an explicit height.
ch — Character Width
input { width: 30ch; } /* fits ~30 characters */
article { max-width: 65ch; } /* optimal reading line length */
clamp() — Min/Max Scaling
h1 { font-size: clamp(1.75rem, 2.5vw + 1rem, 3.5rem); }
.section { padding: clamp(1rem, 5vw, 4rem); }
Quick Reference
| Unit | Relative to | Best for |
|---|---|---|
| px | Absolute | Borders, shadows, icons |
| em | Parent font-size | Component internal spacing |
| rem | Root font-size | Typography, global layout |
| % | Parent dimension | Fluid widths |
| vw/vh | Viewport | Full-bleed, fluid type |
| ch | Character width | Input fields, line length |
| svh/dvh | Viewport (mobile-safe) | Mobile full-height sections |
Recommended Pattern
/* Typography: rem */
body { font-size: 1rem; }
h1 { font-size: clamp(1.75rem, 4vw, 3rem); }
/* Layout: rem */
.container { max-width: 75rem; padding: 0 1rem; }
/* Components: em for internal spacing */
.button { padding: 0.75em 1.5em; }
/* Borders: px */
.card { border: 1px solid #ddd; }
/* Full-bleed: svh */
.hero { min-height: 100svh; }
→ Convert between CSS units instantly with the CSS Unit Converter.