CSS Units Guide — px, em, rem, vw, vh, and When to Use Each
CSS has absolute units (px), relative to font-size (em, rem), viewport units (vw, vh, dvh), and container query units (cqw). Here's when to use each unit and common patterns...
CSS units determine how measurements scale. Using the wrong unit causes layouts that break at different browser font sizes or don’t scale well on mobile. Here’s a practical guide to every major unit.
Use the PX to REM Converter to convert pixel values to rem.
Absolute units
px (pixels)
Fixed size, unaffected by user browser font-size preferences. Fine for borders, shadows, and media query breakpoints. Avoid for font sizes — a user who sets their browser default to 20px expects your text to scale up too.
.border { border: 1px solid #e5e7eb; } /* Good: border */
.shadow { box-shadow: 0 4px 12px rgba(0,0,0,0.1); } /* Good: shadow */
@media (min-width: 768px) { ... } /* Good: breakpoint */
.text { font-size: 16px; } /* Bad: doesn't respect user font prefs */
Relative to font-size
em
Relative to the parent element’s font size (or the current element’s own font size for non-font properties):
.parent { font-size: 20px; }
.child {
font-size: 1.5em; /* = 30px (1.5 × parent's 20px) */
padding: 1em; /* = 30px (1 × the element's own font-size) */
}
/* Problem: em compounds (cascade of em values multiply): */
.parent { font-size: 1.2em; }
.child { font-size: 1.2em; } /* = 1.44× root */
.grandchild { font-size: 1.2em; } /* = 1.728× root — font creep! */
Good uses: padding/margin relative to text size (padding: 0.5em), icon sizing.
rem
Relative to the root element (<html>) font size. No compounding:
html { font-size: 16px; } /* Default browser value */
h1 { font-size: 2rem; } /* = 32px always */
p { font-size: 1rem; } /* = 16px always */
small { font-size: 0.875rem; } /* = 14px always */
/* If user sets browser to 20px base: */
h1 → 40px, p → 20px (scales proportionally — good!)
Use rem for: font sizes, spacing, max-widths, anything that should scale with user font preferences.
Viewport units
vw / vh
Percentage of the viewport width/height:
.hero { height: 100vh; } /* Full screen height */
.title { font-size: 5vw; } /* Scales with viewport width */
/* Problem: 100vh on mobile includes address bar in calculation */
/* Scrolling makes the page jump when bar shows/hides */
dvh (dynamic viewport height) — modern
/* dvh accounts for dynamic UI (address bar, keyboard): */
.hero { height: 100dvh; } /* Correct on mobile */
.hero { height: 100svh; } /* Small viewport (keyboard visible) */
.hero { height: 100lvh; } /* Large viewport (keyboard hidden) */
vmin / vmax
/* vmin = smaller of vw and vh */
/* vmax = larger of vw and vh */
.square { width: 50vmin; height: 50vmin; }
/* Always fits in viewport regardless of orientation */
Container query units (cqw, cqh)
Relative to the container width, not the viewport:
.container { container-type: inline-size; }
.card-title {
font-size: clamp(1rem, 3cqw, 2rem);
/* 3% of container width, clamped between 1rem and 2rem */
}
Other units
/* ch: width of '0' character */
.input { max-width: 30ch; } /* Input fits ~30 characters */
/* ex: height of 'x' character */
/* lh: current line-height */
/* Percentage: relative to parent dimension */
.half { width: 50%; }
/* fr (grid fractions): */
.grid { grid-template-columns: 1fr 2fr 1fr; } /* 25% 50% 25% */
When to use which
| What | Unit | Why |
|---|---|---|
| Font size | rem | Scales with user preference |
| Line height | unitless (1.5) | Relative to current font size |
| Spacing (padding/margin) | rem or em | Scalable with text |
| Borders | px | Crisp, shouldn’t scale |
| Shadows | px | Precise visual effect |
| Full viewport height | dvh | Mobile-safe |
| Fluid typography | clamp() + vw | Scales with viewport |
| Container-based | cqw/cqh | Reusable components |
| Media query breakpoints | em or px | em more accessible |
Related tools
- PX to REM Converter — convert px values to rem
- REM-Based Typography — building a type scale with rem
- Fluid Typography — clamp()-based responsive fonts
Related posts
- Fluid Typography with CSS clamp() — Scale Fonts Without Media Queries — CSS clamp() creates fluid typography that scales smoothly between minimum and ma…
- CSS Design Tokens — Define Spacing, Colors, and Typography with Custom Properties — CSS design tokens store reusable values as custom properties (CSS variables). Le…
- Font Size Accessibility — Minimum Sizes, User Zoom, and WCAG Requirements — WCAG 2.1 doesn't mandate a specific minimum font size, but best practice is 16px…
- PX to REM Conversion — Formula, Table, and CSS Custom Properties — Convert pixel values to rem using the formula rem = px / base-font-size. Include…
- REM-Based Typography — Scalable Font Sizes with rem Units — Using rem for font sizes creates accessible, scalable typography. Text inherits …
Related tool
Convert px to rem, em, and percent — and vice versa. Configurable root font size. Bulk conversion mode for entire stylesheets.
Written by Mian Ali Khalid. Part of the Frontend & Design pillar.