Close-up of well-set body text on a warm paper background showing optimal line length and spacing

Typography and Readability

Typography is the single most consequential design decision on any text-heavy page, and most web layouts get it wrong in predictable ways: line lengths that exceed comfortable reading range, vertical spacing that creates visual monotony, and font choices driven by aesthetic preference rather than functional requirements. This guide covers the practical decisions that improve readability — type scale construction, line length control, vertical rhythm, font pairing, and the specific tradeoffs involved in responsive typography. It is written for designers and front-end developers who ship production layouts and need typography that works across devices, not just on a design comp.

We have set type for hundreds of production pages across editorial sites, documentation platforms, and marketing layouts. The principles here come from measuring real reading behavior, testing across devices, and iterating through the failures that look fine on a 27-inch display but collapse on a phone held in one hand.

Type Scale: Building a Consistent Hierarchy

A type scale is a set of predetermined font sizes that you use across a project. The goal is consistency and predictable relationships between heading levels, body text, subheadings, captions, and interface labels.

The most reliable approach is a modular scale — a sequence of sizes generated by multiplying a base size by a consistent ratio. A base of 16px with a ratio of 1.25 (Major Third) produces: 16, 20, 25, 31.25, 39, 48.8. Round these to practical values and you have a complete type scale.

Google's web.dev typography guidance provides useful foundational reading on responsive type, fluid sizing, and the interaction between viewport dimensions and readability. Understanding these fundamentals prevents the most common scaling mistakes.

Why not just pick sizes that look good? Because ad hoc sizing creates subtle inconsistencies that accumulate across a site. A heading at 28px here, 30px there, 26px on another page — each one is a small decision that erodes visual coherence. A defined scale eliminates these micro-decisions and ensures every text element has a clear hierarchical position.

Line Length: The Most Ignored Readability Factor

Optimal line length for body text is 45–75 characters per line, with 65 characters being the widely cited sweet spot. This is not a stylistic preference — it is a cognitive constraint. Lines that are too long cause the eye to lose track of which line comes next during the return sweep. Lines that are too short interrupt reading flow with constant line breaks.

In practice, controlling line length means setting a max-width on your content container. For body text at 16px with a typical sans-serif font, a max-width of approximately 38em produces roughly 65-character lines. The exact value depends on the specific typeface — wider fonts need narrower containers.

We measure this on every layout we build. The test is simple: type a string of 65 lowercase 'a' characters and see where it wraps. If it wraps before the end of one visual line, your container is too narrow. If it extends well past, your lines are too long.

Vertical Rhythm and Spacing

Vertical rhythm is the consistent application of spacing between text elements. The simplest approach: set a base line-height (typically 1.5 for body text) and make all vertical margins multiples of that base unit.

For a 16px base with 1.5 line-height, the base unit is 24px. Paragraph margins: 24px. Space before an <h2>: 48px (2×). Space after an <h2>: 24px (1×). This creates a visual pulse that makes the page feel ordered even at a subconscious level.

Where vertical rhythm gets tricky is at the boundaries between text and non-text content. Images, code blocks, pull quotes — each one interrupts the rhythm and needs to re-establish it afterward. The practical solution: ensure these elements have bottom margins that are multiples of the base unit, so the next text element falls back onto the rhythm grid.

Font Pairing Strategy

The safest pairing strategy is one serif and one sans-serif — but that is not the real advice. The real advice is: pair fonts that contrast on one axis and harmonise on others.

Good contrast axes:

  • Classification (serif + sans-serif)
  • Weight distribution (light heading + regular body)
  • Width (condensed heading + normal body)

Good harmonisation axes:

  • x-height (both fonts should have similar x-heights at the same point size)
  • Character width (wildly different character widths create jarring transitions)
  • Mood (both should feel like they belong on the same page)

In practice, we default to a system font stack for body text and a single distinctive font for headings. This minimises font loading overhead while still creating visual distinction. The system stack approach has the additional advantage of rendering immediately — no flash of invisible text, no layout shift from font swap.

Checklist

  • [ ] Type scale defined with consistent ratio (no ad hoc sizes)
  • [ ] Body text line length between 45–75 characters
  • [ ] Base line-height set to 1.4–1.6 for body text
  • [ ] Heading line-height tightened (1.1–1.3) for multi-line headings
  • [ ] Vertical margins are multiples of the base line-height unit
  • [ ] Font pairing tested at multiple viewport widths
  • [ ] Font sizes tested on actual mobile devices (not just browser resize)
  • [ ] Contrast ratio meets WCAG AA (4.5:1 for body text, 3:1 for large text)
  • [ ] No text is set below 14px equivalent on mobile
  • [ ] Font loading strategy avoids layout shift (swap, optional, or system stack)

Field-Tested Observations

System font stacks are underrated. We spent years loading custom fonts for body text before realizing that the reading experience with system fonts is often better — the user's device renders its native fonts more consistently, hinting is optimized, and there is zero loading delay. Reserve custom fonts for display use where their personality justifies the performance cost.

Line length problems are invisible to developers. Because we read code in narrow editor columns, our intuition for comfortable reading width is calibrated wrong. We have shipped layouts with 100+ character lines multiple times before catching it, each time because body text looked "fine" on a wide monitor. Measure. Always measure.

Vertical rhythm breaks most often around images. An image with margin-bottom: 20px in a layout with a 24px rhythm unit creates a 4px error that compounds down the page. It is a small thing — but accumulated small things are what separate polished typography from amateur work.

Responsive type needs more than media queries. We use clamp() for fluid typography now — a single declaration that scales smoothly between a minimum and maximum size based on viewport width. The result is typography that adapts continuously rather than jumping between breakpoints.

Common Pitfalls

  1. Setting font sizes in pixels without a scale. Every size becomes a one-off decision, and the system drifts toward inconsistency over months of changes.

  2. Ignoring line length on wide screens. A 1440px-wide text column is physically painful to read. Always constrain body text width.

  3. Using letter-spacing to fix what vertical spacing should solve. Spread-out letters do not improve readability — they make text feel disconnected.

  4. Choosing fonts based on personality alone. A font can be beautiful and completely wrong for body text at 16px on a phone screen.

FAQ

What is the best font size for body text?

16px is the browser default and a solid starting point. On text-heavy editorial pages, we often go to 18px. Below 16px requires excellent contrast and generous line-height to remain comfortable.

Should I use relative units (rem/em) or pixels?

Use rem for font sizes. It respects the user's browser font size preference, which is an accessibility feature you should not override. Use em for margins and padding that should scale proportionally with text size.

How do I handle typography in dark mode?

Reduce font weight slightly — text appears heavier against dark backgrounds due to halation (light spread). If your body text is 400 weight in light mode, consider 300 in dark mode. Also increase line-height slightly; the luminance contrast change affects line tracking.

Is variable font technology worth the complexity?

For sites using multiple weights and styles of a single family — absolutely. A variable font file replacing four or five static files is a significant payload reduction. For sites using one weight of one font, the complexity is not justified.

What line-height should I use for headings?

Tighter than body text — typically 1.1 to 1.3. Large headings with body-text line-height look disconnected; the space between lines exceeds the visual cohesion of the text block. Multi-line headings particularly benefit from tightened leading.

Related Reading