Evidence-based guidelines for readable, accessible typography — sourced from WCAG 2.1/2.2, Material Design 3, Adobe Spectrum, Apple HIG, IBM Carbon, Practical Typography (Butterick), iA Writer research, and e-reader industry practices (Kindle, Apple Books).
| Context | Minimum | Default | Maximum |
|---|---|---|---|
| Mobile | 14px | 16–18px | 28–32px |
| Desktop | 16px | 18–20px | 32–40px |
| User-adjustable | 14px | 18px | 32–36px |
Always use rem for font sizes, never px. This ensures browser zoom and user font-size preferences are respected.
WCAG 1.4.4 (Resize Text, Level AA): Text must remain functional when scaled to 200% of authored size.
Use a modular scale rather than linear increments. Linear steps (+2px each) feel uneven — small sizes barely change while large sizes jump noticeably. A modular scale ensures each step feels proportionally the same.
This matches what Kindle and Apple Books use. Each step is ~20% larger than the previous.
| Step | Label | Size (rem) | Size (px) | Use case |
|---|---|---|---|---|
| 1 | XS | 0.875 | 14 | Accessibility minimum |
| 2 | S | 1.0 | 16 | Browser default |
| 3 | M | 1.125 | 18 | Comfortable default |
| 4 | L | 1.3125 | 21 | Larger |
| 5 | XL | 1.5 | 24 | Extra large |
| 6 | 2XL | 1.75 | 28 | Low vision |
| 7 | 3XL | 2.0 | 32 | Very low vision |
| Scale | Ratio | Steps 14→32px | Best for |
|---|---|---|---|
| Major Second | 1.125x | ~8 steps | Fine granularity (Adobe Spectrum) |
| Minor Third | 1.2x | ~6–7 steps | Reading apps (Kindle-like) |
| Major Third | 1.25x | ~5 steps | Fewer, bolder steps |
| Perfect Fourth | 1.333x | ~4 steps | Heading hierarchies |
Line-height ratio must decrease as font size increases. This is the most important and most commonly overlooked typography rule.
At small sizes, text needs more vertical breathing room to remain readable. At large sizes, the absolute pixel gap between lines is already substantial — maintaining the same ratio creates excessive whitespace.
| Font size | Line-height ratio | Computed line-height |
|---|---|---|
| 14px | 1.6 | 22.4px |
| 16px | 1.55 | 24.8px |
| 18px | 1.5 | 27.0px |
| 21px | 1.45 | 30.5px |
| 24px | 1.4 | 33.6px |
| 28px | 1.35 | 37.8px |
| 32px | 1.3 | 41.6px |
line-height: 1.5 without clipping or overlap. This is a survivability floor, not an ideal.For continuous scaling (e.g., with a slider):
line-height = font-size × (1.6 - 0.01 × font-size-in-px)
Clamped to the range [1.2, 1.6].
Use unitless line-height values so they inherit correctly:
/* Good — unitless, inherits proportionally */
line-height: 1.5;
/* Bad — fixed px, doesn't adapt to font size changes */
line-height: 24px;
45–90 characters per line, with 65 characters as the classical typographic ideal.
Use ch units for container width — this automatically adapts when font size changes:
.reading-container {
max-width: 65ch; /* ~65 characters wide */
}
When users increase font size, the container (in ch) stays the same number of characters wide, but grows in absolute pixels. The text naturally reflows with fewer characters per line at the larger size — which is correct behavior.
Never use fixed px widths for reading containers. If you must use pixels, scale the container proportionally with font size.
Leave letter spacing at 0 for body text. Well-designed typefaces have correct tracking built in. Fighting the typeface's built-in spacing reduces readability.
Your layout must not break when users apply these overrides (via browser extensions or assistive technology):
| Property | Minimum override to survive |
|---|---|
| Letter spacing | 0.12em |
| Word spacing | 0.16em |
| Line height | 1.5x font size |
| Paragraph spacing | 2x font size |
Test this: Apply all four overrides simultaneously. Nothing should clip, overlap, or become hidden.
If offering a "dyslexia-friendly" mode, increase letter spacing to 0.05–0.12em. Research (McLeish study, cited by WCAG) shows this measurably improves readability for dyslexic users.
margin-bottom: 1em to 1.5em — scales automatically with font size.margin-bottom: 2em or more.Verse text is typically presented as continuous prose (not separated paragraphs). Use:
margin-right: 0.2em).margin-bottom: 1.25em between paragraphs.When users change font size, other properties should scale proportionally. Using em/ch units makes this automatic:
| Property | Should scale? | Unit to use | Notes |
|---|---|---|---|
| Font size | Yes (user control) | rem |
The primary control |
| Line height | Yes, sub-linearly | Unitless ratio | Ratio decreases at larger sizes |
| Letter spacing | Auto-scales | em |
Leave at 0 for body text |
| Word spacing | Auto-scales | em |
Leave at default |
| Paragraph spacing | Auto-scales | em |
margin-bottom: 1.25em |
| Container width | Auto-scales | ch |
max-width: 65ch |
| Padding | Auto-scales | em |
Keeps proportional breathing room |
| Verse number size | Auto-scales | em |
font-size: 0.7em on superscript |
rem, never pxline-height: 1.5; letter-spacing: 0.12em; word-spacing: 0.16em; p margin-bottom: 2emch units (target 65ch)em unitstransition: font-size 0.2s ease)Font size: 14px → 16px → 18px → 21px → 24px → 28px → 32px
(XS) (S) (M*) (L) (XL) (2XL) (3XL)
Line height: 1.6 → 1.55 → 1.5 → 1.45 → 1.4 → 1.35 → 1.3
Line length: 65ch container (45–90 char range)
Spacing: margin-bottom: 1.25em (paragraphs)
letter-spacing: 0 (body), 0.05–0.12em (dyslexia mode)
Units: font-size: rem | line-height: unitless | spacing: em | width: ch