CSS Units Comparison

px, em, rem, vh, vw, % — when to use each and why

All CSS Units at a Glance

UnitTypeRelative ToBest For
pxAbsoluteDevice pixelBorders, shadows, small fixed values
remRelativeRoot font sizeFont sizes, spacing, consistent scaling
emRelativeParent font sizeComponent-local sizing, button padding
%RelativeParent elementWidths, fluid layouts
vhViewportViewport heightFull-screen sections
vwViewportViewport widthFull-bleed elements
dvhViewportDynamic viewport heightMobile full-screen (accounts for URL bar)
chRelativeWidth of "0" characterMax text width (e.g., 65ch for readability)
vminViewportSmaller viewport dimensionSquare elements relative to viewport
vmaxViewportLarger viewport dimensionElements that fill any orientation

px — The Absolute Unit

Pixels are fixed. 16px is always 16px regardless of parent size, root font size, or viewport. Use them for things that should not scale:

.element { border: 1px solid #e2e8f0; /* borders */ box-shadow: 0 2px 4px rgba(0,0,0,0.1); /* shadows */ outline-offset: 2px; /* focus outlines */ }

Avoid px for font sizes and spacing — they do not respect user accessibility settings.

rem — Root-Relative

1rem = the root element’s font size (default 16px). It never compounds, making it predictable:

html { font-size: 16px; } /* or leave as browser default */ h1 { font-size: 2rem; } /* 32px */ h2 { font-size: 1.5rem; } /* 24px */ p { font-size: 1rem; } /* 16px */ .container { padding: 1.5rem; /* 24px */ gap: 1rem; /* 16px */ max-width: 75rem; /* 1200px */ }
1rem = 16px (root)
0.75rem = 12px
1.25rem = 20px

Use rem for: font sizes, padding, margins, gaps, max-widths. It scales when users change their browser font size setting.

em — Parent-Relative

1em = the element’s own computed font size. For the font-size property specifically, it is relative to the parent’s font size. This means em compounds when nested:

.parent { font-size: 20px; } .child { font-size: 1.2em; } /* 24px (20 * 1.2) */ .grandchild { font-size: 1.2em; } /* 28.8px (24 * 1.2) -- compounding! */

Good use case: padding on buttons that should scale with text size:

.btn { padding: 0.5em 1em; /* scales with font-size */ } .btn-sm { font-size: 0.8rem; } /* padding shrinks proportionally */ .btn-lg { font-size: 1.2rem; } /* padding grows proportionally */

vh, vw — Viewport Units

1vh = 1% of viewport height. 1vw = 1% of viewport width.

/* Full-screen hero section */ .hero { min-height: 100vh; } /* Full-bleed background */ .full-bleed { width: 100vw; margin-left: calc(-50vw + 50%); }

Mobile gotcha: 100vh on mobile includes the space behind the browser’s URL bar, causing content to be cut off. Use 100dvh (dynamic viewport height) instead:

.hero { min-height: 100dvh; /* accounts for mobile URL bar */ /* Fallback for older browsers */ min-height: 100vh; min-height: 100dvh; }

% — Parent-Relative

Percentage is relative to the parent element. What it is relative to depends on the property:

ch — Character Width

1ch equals the width of the “0” character in the current font. Useful for readable text widths:

.prose { max-width: 65ch; /* roughly 65 characters per line */ margin: 0 auto; } .code-input { width: 40ch; /* sized for ~40 characters */ }

clamp() — Fluid Sizing

Combine units with clamp(min, preferred, max) for responsive values without media queries:

h1 { /* Min 1.5rem, preferred 4vw, max 3rem */ font-size: clamp(1.5rem, 4vw, 3rem); } .container { /* Fluid padding */ padding: clamp(1rem, 3vw, 3rem); } .card-grid { gap: clamp(12px, 2vw, 32px); }

clamp() is the best way to handle fluid typography and spacing. The value smoothly scales between the min and max based on the preferred unit.

Quick Recommendations

PropertyUseWhy
font-sizerem or clamp()Respects user preferences, scales consistently
padding, margin, gapremConsistent, predictable spacing
width% or frFluid layouts
max-widthrem or chContent-appropriate limits
border, outlinepxShould not scale
full-screen heightdvhWorks on mobile
button paddingemScales with button text size

Frequently Asked Questions

Should I use px or rem for font size?
Use rem. It respects the user’s browser font size setting (important for accessibility). px ignores user preferences. 1rem = the root font size (typically 16px). Use clamp() for fluid typography.
What is the difference between em and rem?
em is relative to the current element’s font size and compounds when nested. rem is always relative to the root font size and never compounds. Use rem for consistency. Use em when you want sizing proportional to the local font size (like button padding).
When should I use vh and vw?
vh for full-screen sections (min-height: 100vh). vw for full-bleed elements. Avoid vw for font sizes without clamp(). On mobile, use dvh instead of vh to account for the browser URL bar.

Related Tools