1. Unit Basics: px, rem, and em

Use rem for global sizing, em for local component scaling, and px for precise one-off values like borders or icons.

px vs rem

18px text

1.125rem text

rem follows the root font size and improves accessibility.

em nesting

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; }

2. Readability Units: ch

ch helps control line length. Around 45 to 75 characters per line usually reads best for paragraphs.

Paragraph width with ch

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;
}

3. Viewport Units: vw and vh

Viewport units are useful for hero sections and visual blocks. Combine them with limits to avoid extreme sizes.

vw width

Use min() and max() with viewport units for better control.

vh panel
Height follows viewport

vh is useful for sections, modals, and full-screen layouts.

.hero-title { font-size: min(8vw, 4rem); }
.hero-panel { min-height: min(60vh, 32rem); }

4. Fluid Sizing with clamp()

clamp(min, preferred, max) gives smooth scaling while keeping sensible limits.

Fluid heading

Resize this window

Fluid headings reduce breakpoint complexity in responsive design.

Fluid spacing
Padding uses clamp()

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); }

5. Token Pattern for Scales

Use CSS custom properties to define reusable spacing and typography scales once, then apply them consistently.

Scale tokens

Token-based Card

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);
}