CSS Units Comparison
All CSS Units at a Glance
| Unit | Type | Relative To | Best For |
|---|---|---|---|
px | Absolute | Device pixel | Borders, shadows, small fixed values |
rem | Relative | Root font size | Font sizes, spacing, consistent scaling |
em | Relative | Parent font size | Component-local sizing, button padding |
% | Relative | Parent element | Widths, fluid layouts |
vh | Viewport | Viewport height | Full-screen sections |
vw | Viewport | Viewport width | Full-bleed elements |
dvh | Viewport | Dynamic viewport height | Mobile full-screen (accounts for URL bar) |
ch | Relative | Width of "0" character | Max text width (e.g., 65ch for readability) |
vmin | Viewport | Smaller viewport dimension | Square elements relative to viewport |
vmax | Viewport | Larger viewport dimension | Elements 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:
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:
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:
Good use case: padding on buttons that should scale with text size:
vh, vw — Viewport Units
1vh = 1% of viewport height. 1vw = 1% of viewport width.
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:
% — Parent-Relative
Percentage is relative to the parent element. What it is relative to depends on the property:
width: 50%— 50% of parent’s widthpadding: 10%— 10% of parent’s width (yes, even padding-top/bottom)font-size: 120%— 120% of parent’s font size (same as 1.2em)height: 100%— only works if parent has a defined height
ch — Character Width
1ch equals the width of the “0” character in the current font. Useful for readable text widths:
clamp() — Fluid Sizing
Combine units with clamp(min, preferred, max) for responsive values without media queries:
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
| Property | Use | Why |
|---|---|---|
| font-size | rem or clamp() | Respects user preferences, scales consistently |
| padding, margin, gap | rem | Consistent, predictable spacing |
| width | % or fr | Fluid layouts |
| max-width | rem or ch | Content-appropriate limits |
| border, outline | px | Should not scale |
| full-screen height | dvh | Works on mobile |
| button padding | em | Scales with button text size |
Frequently Asked Questions
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.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).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.