18px text
1.125rem text
rem follows the root font size and improves accessibility.
Picking the right unit makes your UI easier to scale and easier to maintain. This guide covers practical patterns for rem, em, viewport units, and clamp().
Use rem for global sizing, em for local component scaling, and px for precise one-off values like borders or icons.
18px text
1.125rem text
rem follows the root font size and improves accessibility.
Parent at 1.25rem
Child at 1.2em
em is relative to the current element and useful for component-level scaling.
html { font-size: 16px; }
body { font-size: 1rem; }
h2 { font-size: 1.5rem; }
.component { font-size: 1.125rem; }
.component small { font-size: 0.85em; }ch helps control line length. Around 45 to 75 characters per line usually reads best for paragraphs.
This paragraph is constrained with ch units so line length stays readable on larger screens without manual breakpoint tuning.
Use max-width: 60ch for long-form text containers.
.article {
max-width: 60ch;
line-height: 1.7;
}Viewport units are useful for hero sections and visual blocks. Combine them with limits to avoid extreme sizes.
Use min() and max() with viewport units for better control.
vh is useful for sections, modals, and full-screen layouts.
.hero-title { font-size: min(8vw, 4rem); }
.hero-panel { min-height: min(60vh, 32rem); }clamp(min, preferred, max) gives smooth scaling while keeping sensible limits.
Resize this window
Fluid headings reduce breakpoint complexity in responsive design.
You can apply the same pattern to gaps, margins, and card padding.
.title { font-size: clamp(1.5rem, 4vw, 3rem); }
.card { padding: clamp(0.75rem, 2vw, 2rem); }
.stack { gap: clamp(0.5rem, 1.2vw, 1rem); }Use CSS custom properties to define reusable spacing and typography scales once, then apply them consistently.
Spacing tokens keep components aligned across pages.
Tokenized values improve consistency and make global tuning faster.
:root {
--space-1: 0.5rem;
--space-2: 1rem;
--space-3: clamp(1rem, 2vw, 1.5rem);
}
.card {
padding: var(--space-3);
gap: var(--space-2);
}