A comprehensive guide to CSS length units — understand the difference between absolute and relative units and build accessible, responsive layouts.
CSS length units fall into two categories:
Knowing which category to reach for — and which reference value a relative unit uses — is the key to writing maintainable, accessible CSS.
CSS pixels are a logical unit defined as 1/96th of an inch at 96 DPI. On high-DPI (Retina) displays, one CSS pixel may map to 2 or 3 physical device pixels.
/* Fixed sizes — predictable but inflexible */
.button { padding: 8px 16px; border: 1px solid; }
.avatar { width: 40px; height: 40px; border-radius: 50%; }
.divider { border-top: 1px solid; }
Use px for: Borders, box shadows, fine-grained spacing adjustments, minimum sizes, anything that should never scale.
Avoid px for: Font sizes. Users who increase their browser font size for accessibility will have your px font sizes stay fixed, breaking their preference.
rem is relative to the root element's (<html>) font size. The default browser font size is 16px, so 1rem = 16px unless changed.
:root {
font-size: 16px; /* 1rem = 16px */
}
h1 { font-size: 2rem; } /* 32px */
h2 { font-size: 1.5rem; } /* 24px */
p { font-size: 1rem; } /* 16px */
.small { font-size: 0.875rem; } /* 14px */
/* Spacing also works well in rem */
.card { padding: 1.5rem; margin-bottom: 2rem; }
Why rem is excellent for font sizes: If a user sets their browser font size to 20px, your entire type scale scales up proportionally. This is the foundation of accessible typography.
Practical trick — 62.5% base:
:root { font-size: 62.5%; } /* 1rem = 10px */
/* Now 1.6rem = 16px, 2.4rem = 24px */
em is relative to the current element's computed font size. If the element has no explicit font size, it inherits from its parent.
/* em for padding — scales with the element's own font size */
.button {
font-size: 1rem;
padding: 0.5em 1em; /* 8px 16px at default */
}
.button.large {
font-size: 1.25rem;
/* padding automatically becomes 10px 20px */
}
Gotcha — em compounds:
/* If parent has font-size: 2em, child 2em = 4x the root */
.parent { font-size: 2em; }
.child { font-size: 2em; } /* Actually 4x root! */
Best uses for em: Padding and margins on interactive components (so they scale with the component's font size), media queries based on content width.
1vw = 1% of viewport width1vh = 1% of viewport height1svh = 1% of small viewport height (accounts for mobile browser chrome)/* Full-screen hero section */
.hero { height: 100vh; }
/* Fluid typography that scales with viewport width */
.heading {
font-size: clamp(1.5rem, 5vw, 3rem);
/* Min 24px, preferred 5% of viewport, max 48px */
}
/* Horizontal padding that grows with viewport */
.container { padding-inline: clamp(1rem, 5vw, 4rem); }
Mobile viewport gotcha: 100vh includes the mobile browser UI (address bar). Use 100svh (small viewport height) for content that should fit visible screen space.
Percentage is relative to the parent element's corresponding property:
/* Width: percentage of parent's width */
.column { width: 50%; }
/* Padding/margin: percentage of parent's WIDTH (not height!) */
.aspect-ratio {
padding-bottom: 56.25%; /* 16:9 aspect ratio trick */
}
/* For transformations: relative to the element itself */
.centered {
transform: translate(-50%, -50%);
}
| Use case | Unit |
|---|---|
| Font sizes | rem |
| Component padding/margin | em or rem |
| Borders, shadows | px |
| Layout widths | %, vw, or fr (CSS Grid) |
| Full-screen sections | 100vh / 100svh |
| Fluid typography | clamp(rem, vw, rem) |
| Minimum/maximum sizes | px or rem |
Use HeoLab's CSS Unit Converter to instantly convert between px, rem, em, vw, vh, pt, cm, mm, and inches. Set your base font size and viewport dimensions for accurate relative conversions.
The rule of thumb: use rem for font sizes and spacing, px for fine details and borders, viewport units for layout, and % for fluid widths. Avoid px for font sizes if you care about accessibility. Use clamp() for fluid typography that respects both minimum sizes and user preferences.