Guides / Typography
text_fields

Web Typography Guide: Scales, Spacing & Readability

Typography is 95% of design. It determines readability, hierarchy, emotion, and brand voice. This guide covers the principles and CSS techniques that separate professional typographic systems from amateur ones.

April 2026 · 10 min read

The Typographic Scale

A typographic scale is a set of harmonically related font sizes. The modular scale (each step multiplied by a ratio) creates visual consistency across heading levels.

/* Modular scale with ratio 1.25 (Major Third) */
:root {
  --text-xs:   0.64rem;   /* 10.24px */
  --text-sm:   0.8rem;    /* 12.8px */
  --text-base: 1rem;      /* 16px */
  --text-lg:   1.25rem;   /* 20px */
  --text-xl:   1.563rem;  /* 25px */
  --text-2xl:  1.953rem;  /* 31px */
  --text-3xl:  2.441rem;  /* 39px */
  --text-4xl:  3.052rem;  /* 49px */
}

/* Usage */
h1 { font-size: var(--text-4xl); }
h2 { font-size: var(--text-3xl); }
h3 { font-size: var(--text-2xl); }
h4 { font-size: var(--text-xl); }
p  { font-size: var(--text-base); }
small { font-size: var(--text-sm); }

Fluid Typography with clamp()

clamp(min, preferred, max) creates type that scales smoothly between breakpoints without media queries. The preferred value uses viewport units for fluid scaling.

/* Fluid heading: 2rem on mobile → 4rem on desktop */
h1 {
  font-size: clamp(2rem, 4vw + 1rem, 4rem);
}

/* Fluid body text: 1rem → 1.125rem */
p {
  font-size: clamp(1rem, 0.5vw + 0.875rem, 1.125rem);
}

/*
  clamp() formula:
  - min: smallest size (mobile)
  - preferred: vw-based calculation for smooth scaling
  - max: largest size (desktop)

  Tip: use utopia.fyi to generate fluid type scales automatically
*/

/* Full fluid scale example */
:root {
  --step-0: clamp(1rem, 0.5vi + 0.875rem, 1.125rem);
  --step-1: clamp(1.25rem, 1vi + 1rem, 1.5rem);
  --step-2: clamp(1.5rem, 2vi + 1rem, 2rem);
  --step-3: clamp(2rem, 3vi + 1rem, 3rem);
  --step-4: clamp(2.5rem, 5vi + 1rem, 4rem);
}

Line Height: The Most Impactful Typography Setting

Line height (leading) has more impact on readability than font size. Too tight creates claustrophobia; too loose breaks the sense of grouping.

/* Line height ratios by context */
:root {
  --leading-tight:   1.2;  /* headings, large display type */
  --leading-snug:    1.35; /* subheadings, labels */
  --leading-normal:  1.5;  /* UI text, captions */
  --leading-relaxed: 1.65; /* body text, articles */
  --leading-loose:   1.8;  /* long-form reading, accessibility */
}

h1, h2 { line-height: var(--leading-tight); }
h3, h4 { line-height: var(--leading-snug); }
p      { line-height: var(--leading-relaxed); }

/* Rule of thumb:
   - Headings (large text): 1.1–1.3
   - Body text: 1.5–1.7
   - Small/caption text: 1.4–1.6 (needs more leading, not less)
*/

Measure: Optimal Line Length

Measure is the width of a column of text. The ideal is 45–75 characters per line. Too wide: eyes lose track of the next line. Too narrow: constant line breaks disrupt flow.

/* Using ch units (1ch = width of '0' character) */
article, .prose {
  max-width: 70ch; /* approximately 65-75 characters */
}

/* More precise with character count test:
   "The quick brown fox jumps over the lazy dog" = 44 chars
   Adjust max-width until a typical paragraph line is 50-70 chars
*/

/* For multiple column sizes */
.caption { max-width: 45ch; }
.body    { max-width: 70ch; }
.lead    { max-width: 55ch; }

Letter Spacing (Tracking)

Default letter spacing works for body text. Adjust for specific contexts: uppercase labels need positive tracking; large display headings often benefit from negative tracking.

/* Context-appropriate letter spacing */
/* All-caps labels, buttons, overlines */
.label, .overline, .badge {
  text-transform: uppercase;
  letter-spacing: 0.05em;  /* 0.05–0.1em for uppercase */
  font-size: 0.75rem;
}

/* Display headings (tighten at large sizes) */
.display-xl {
  font-size: clamp(3rem, 6vw, 6rem);
  letter-spacing: -0.02em; /* tighter at large sizes */
}

/* Body text */
p {
  letter-spacing: 0; /* or 0.01em for optical correction */
}

/* Never: tracking sans-serif body text positively
   Only tracking all-caps or small type positively */

Font Pairing Archetypes

Pairing TypeHeadingBodyCharacter
Classic editorialPlayfair DisplaySource Serif 4Authoritative, literary
Modern techInterInterClean, neutral, readable
Warm humanistLoraSource Sans 3Approachable, editorial
High contrastMontserratMerriweatherStrong, magazine-like
Minimal UIDM SansDM SansSystemic, app-like

Common Typography Mistakes

  • Body text below 16px — 16px is the minimum comfortable reading size. 17–18px is better for long-form content.
  • Using heading font for body text — display/heading fonts are designed for large sizes. At small sizes they lose legibility. Use a text-optimized typeface for body.
  • 100% line-height on body text — this makes lines collide. Always set line-height explicitly; browser defaults vary.
  • Positive letter-spacing on lowercase body text — spacing is set by the type designer for lowercase text. Expanding it hurts readability; only expand tracking on uppercase.
  • Using more than 2–3 typefaces — every additional font family adds cognitive noise and network overhead. 1 family (with multiple weights) or 2 families is almost always enough.

Frequently Asked Questions

What is the best font size for body text?
16px is the conventional baseline. For long-form reading (articles, documentation), 17–18px with 1.6–1.7 line-height is more comfortable, especially on large screens.
Should I use rem or px for font sizes?
rem (root em) respects the user's browser font-size preferences — important for accessibility. Users who've set their browser default to 20px because they need larger text will have that preference respected with rem but not with px.
How do I choose a font pairing?
The most reliable approach: pair a geometric/grotesque sans-serif with a humanist serif from the same period, or use a single superfamily with both display and text cuts (like Inter, Merriweather, or Source). Contrast in style (sans + serif) is safer than matching two different sans-serifs.
What is a variable font and should I use one?
A variable font contains an entire type family (weights, widths, optical sizes) in a single file. One file replaces 4–8 separate font files, with significant bandwidth savings. All major Google Fonts support variable fonts now — use them.

Free reference

The 47 Tools Cheat Sheet

One printable page with every tool on this site, what it does, and when to reach for it. Free. It asks for an email so Gumroad can send you the file, unlike the tools themselves.