Body text and reading
Running text is the only place where typography is measured against a physical
process: the eye's saccadic movement. Every rule here derives from that, not from
taste.
1. When to invoke
- Setting body copy for anything read in succession (>1 paragraph).
- A reader reports strain, re-reading lines, or losing their place.
- Choosing or changing body size, line-height, or column width.
- Auditing an existing article/doc template.
Do not invoke for isolated UI strings, labels, or numeric displays — that is
ui-component-typography. Do not invoke for headings alone — that is
hierarchy-and-scale.
2. Required context
Refuse to give a number until you have, or have explicitly assumed:
- The typeface and its x-height (apparent size varies enormously at equal
nominal size).
- Target device and reading distance (phone ~35cm, laptop ~50–70cm, TV ~3m,
kiosk standing).
- Content type — reference/scanned vs. immersive/continuous.
- Audience — age, vision, whether Dynamic Type / user zoom is expected.
- Available column width, and whether it is fixed or fluid.
If you have none of these, say what you're assuming before you answer.
3. Invariant principles
- Information is absorbed only during fixations, not during motion. The eye
moves in saccades of roughly 5–10 letters (~1–2 English words) alternating with
fixations of 0.2–0.4 seconds. Only 3–4 letters are focused sharply; the rest are
perceived indistinctly and from context. Unclear text causes regression
saccades — the eye jumps back. (Hochuli)
- Size, line-height, and measure are one interdependent system. Change one and
you must revisit the other two. Latin calls it a triangle that must stay
equilateral.
- The line-return must be unambiguous. If a reader's eye cannot reliably find
the start of the next line, the setting has failed, whatever its metrics.
- Serif vs. sans is not a readability decision. Research has failed to prove
serifs improve reading speed or comprehension; "bias favors familiarity."
(Lupton) Choose on tone and rendering.
- Text must survive user override. WCAG 1.4.12 requires no loss of content or
functionality at
line-height: 1.5, paragraph spacing 2em, word spacing
0.16em, letter spacing 0.12em. WCAG 1.4.4 requires 200% resize.
4. Context-dependent heuristics
Measure. Use 45–75 characters as a diagnostic range, not a target.
| Situation |
Guidance |
| Desktop, single column, continuous reading |
60–75 is comfortable; check visually |
| Phone at default size |
~40 CPL is normal and acceptable — the device floor wins |
| Below ~35 CPL |
Real defect: too many line-returns, ragged texture |
| Above ~85 CPL |
Real defect regardless of viewport |
| Inside the range |
Judge with your eyes; do not tune to hit a count |
The canon genuinely disagrees here (Lupton 55–70, Rutter 45–75, Material 40–60,
Brown rejecting counting altogether). See ../type/references/corpus-conflicts.md.
Field trick (Walton, via Stocks): put an asterisk before the 45th character and
after the 75th, then see where lines actually break.
Size. Start from the browser default (commonly 16px) as a starting point, not
an optimum. Then adjust for apparent size: a face with a tall x-height at 16px
reads larger than one with a short x-height at the same value. Match apparent
size, not nominal size, when swapping typefaces.
Line-height. 1.3–1.7 unitless for body text is the working range (Latin);
Santa Maria's range is close but wider, 1.2–1.8, and she's explicit that "a true
ideal line-height doesn't exist" — the typeface's design (wide/decorative faces
want more air) and the specific setting (a narrow hanging caption can run tighter
than the article beside it) both move the number, so treat any range as a
starting point to trial against the real typeface, not a value to look up. Push
higher as measure lengthens — a long line needs more vertical separation for
the return sweep to land correctly. Push lower as measure shortens. Tighter than
1.3 for a full paragraph is almost always wrong. Always use a unitless value so
it inherits proportionally.
Don't ship the default leading. Elam's observation about how designers actually
work: "initially, many designers are satisfied with the computer default values for
leading, about 20% of the text size" — i.e. roughly 1.2 — and the discipline is to
"become sensitive to the texture of the text on the page," then investigate leading
deliberately and "experiment with dense and airy text." A 1.2 line-height in a
paragraph is usually a default nobody chose. See microtypography on typographic
colour for reading that texture.
Reading distance scales everything. Kiosk and TV need far larger sizes than
their "equivalent" desktop values. To evaluate this honestly rather than guess,
Brown's technique: zoom the rendered composition to simulate the actual viewing
distance (or better, view it on a real device at its real distance — phone in
hand, TV across a room) and re-judge size and measure at that simulated
closeness, not at your editor's default zoom level.
5. Failure patterns
| Pattern |
Cause |
Fix |
| Reader loses their place mid-paragraph |
Measure too long for the line-height |
Shorten measure or increase line-height |
| Text feels dense and airless |
Line-height too tight, or x-height tall with tight spacing |
Raise line-height; check letter spacing |
| Lines drift apart, paragraph stops cohering |
Line-height too large for the measure |
Reduce line-height or lengthen measure |
| Fine on desktop, cramped on phone |
Fixed px sizing, no fluid strategy |
Route to responsive-typography |
| Breaks when the user zooms or applies a spacing override |
Fixed heights, overflow: hidden, absolute positioning |
Route to typography-accessibility |
| Swapping the font changed the whole page rhythm |
Matched nominal size instead of apparent size |
Re-tune size to x-height, then re-check measure |
6. Evaluation procedure
Run in order. Stop and fix before continuing.
- Render it. Never evaluate body text from CSS alone.
- Count characters on 3 representative full lines. Compare against the
diagnostic range for that viewport.
- Read one full paragraph at real size and distance. Did your eye return
cleanly on every line?
- Set
line-height: 1.5, word-spacing: .16em, letter-spacing: .12em,
paragraph spacing 2em. Confirm nothing clips, overlaps, or disappears
(WCAG 1.4.12).
- Zoom to 200%. Confirm no loss of content or function (WCAG 1.4.4).
- Check the narrowest and widest supported viewport.
- Check contrast ≥ 4.5:1 for normal text (WCAG 1.4.3).
7. Output format
Setting: <typeface> <size> / <line-height> at <measure>
Inputs: x-height <tall|moderate|short>, device <…>, distance <…>, content <…>
Measure: <N> CPL at <viewport> — <inside|below|above> diagnostic range
Checks: 1.4.12 <pass/fail> · 1.4.4 <pass/fail> · 1.4.3 <ratio>
Conflicts resolved: <which rule won, if any>
Unverified: <anything not checked in a rendered context>
8. Examples
Documentation site, desktop-first, Source Sans (moderate x-height).
Starting at the 16px browser default. Source Sans has a moderate x-height, so
apparent size is close to nominal — no compensation needed. At a 68ch column the
measure lands ~70 CPL, inside range. Line-height 1.6 unitless, toward the upper
end because the measure is long. Verified at 200% zoom and under a 1.5
line-height override: no clipping.
Swapping Georgia → Merriweather in an existing article template.
Merriweather has a notably larger x-height, so at the same 18px it reads
distinctly larger and the existing 66ch measure now runs ~74 CPL. Two options:
drop to 17px to match apparent size and preserve the measure, or keep 18px and
narrow the column. Recommending the size drop — it preserves the tuned measure
and the page rhythm.
9. Counterexamples
- ❌ "Body text should be 16px with 1.5 line-height." — A universal constant with
no inputs. Wrong for a kiosk, a phone, a TV, or any face with an unusual
x-height.
- ❌ "Use a serif for body text because serifs are more readable." — Unevidenced.
Lupton is explicit that research has failed to demonstrate this.
- ❌ "Measure is 45–75 characters, so I set it to exactly 60ch." —
ch is the
width of the 0 glyph and varies per font; and tuning to hit a count produces
the stiff layouts Brown warns about.
- ❌ "It passes contrast, so the body text is accessible." — 1.4.3 is one of three
relevant criteria; 1.4.4 and 1.4.12 are independent.
- ❌ Setting
line-height: 24px. Fixed units break inheritance and user scaling.
10. Source citations
- Hochuli, Detail in Typography — the reading process; saccades, fixation
duration, regression saccades. Primary source for why any of this matters.
- Lupton, Thinking with Type 3e — measure 55–70; serif readability research is
inconclusive; familiarity bias.
- Rutter, Web Typography — 45–75 range; 42 CPL satisfactory; ~40 CPL on a
phone at default size; apparent size and x-height compensation.
- Brown, Flexible Typesetting — measure as a visual decision; Frere-Jones,
"we read with our eyes, not with rulers"; zooming a composition to simulate
real viewing distance/closeness as an evaluation technique, rather than judging
size at an editor's default zoom.
- Latin, Better Web Typography — 1.3–1.7 line-height; the size/line-height/
measure triangle.
- Santa Maria, On Web Typography — 1.2–1.8 line-height as a starting range;
there's no universal ideal, it's set per typeface and per setting (a narrow
hanging caption legitimately tighter than the body beside it).
- Lupton (ed.), Type on Screen — 45–75 measure on screen.
- Elam, Typographic Systems of Design — default leading of about 20% of text size
as a starting point designers too readily accept; developing sensitivity to the
texture of the text; experimenting with dense and airy settings.
- Stocks, Universal Principles of Typography — Bringhurst's 66; Material's
40–60; Walton's asterisk trick.
- WCAG 2.2 §1.4.3, §1.4.4, §1.4.12.
1---2name: body-text-and-reading3description: Use when setting or fixing running text meant to be read continuously — article bodies, documentation, long-form pages, onboarding copy, email. Also use when readers report eye strain, losing their place, re-reading lines, or text that "feels dense", and when choosing body size, line-height, or measure.4---56# Body text and reading78Running text is the only place where typography is measured against a physical9process: the eye's saccadic movement. Every rule here derives from that, not from10taste.1112## 1. When to invoke1314- Setting body copy for anything read in succession (>1 paragraph).15- A reader reports strain, re-reading lines, or losing their place.16- Choosing or changing body size, line-height, or column width.17- Auditing an existing article/doc template.1819**Do not** invoke for isolated UI strings, labels, or numeric displays — that is20`ui-component-typography`. Do not invoke for headings alone — that is21`hierarchy-and-scale`.2223## 2. Required context2425Refuse to give a number until you have, or have explicitly assumed:2627- The **typeface** and its x-height (apparent size varies enormously at equal28 nominal size).29- **Target device and reading distance** (phone ~35cm, laptop ~50–70cm, TV ~3m,30 kiosk standing).31- **Content type** — reference/scanned vs. immersive/continuous.32- **Audience** — age, vision, whether Dynamic Type / user zoom is expected.33- **Available column width**, and whether it is fixed or fluid.3435If you have none of these, say what you're assuming before you answer.3637## 3. Invariant principles3839- **Information is absorbed only during fixations, not during motion.** The eye40 moves in saccades of roughly 5–10 letters (~1–2 English words) alternating with41 fixations of 0.2–0.4 seconds. Only 3–4 letters are focused sharply; the rest are42 perceived indistinctly and from context. Unclear text causes *regression43 saccades* — the eye jumps back. (Hochuli)44- **Size, line-height, and measure are one interdependent system.** Change one and45 you must revisit the other two. Latin calls it a triangle that must stay46 equilateral.47- **The line-return must be unambiguous.** If a reader's eye cannot reliably find48 the start of the next line, the setting has failed, whatever its metrics.49- **Serif vs. sans is not a readability decision.** Research has failed to prove50 serifs improve reading speed or comprehension; "bias favors familiarity."51 (Lupton) Choose on tone and rendering.52- **Text must survive user override.** WCAG 1.4.12 requires no loss of content or53 functionality at `line-height: 1.5`, paragraph spacing `2em`, word spacing54 `0.16em`, letter spacing `0.12em`. WCAG 1.4.4 requires 200% resize.5556## 4. Context-dependent heuristics5758**Measure.** Use **45–75 characters as a diagnostic range, not a target.**5960| Situation | Guidance |61|---|---|62| Desktop, single column, continuous reading | 60–75 is comfortable; check visually |63| Phone at default size | ~40 CPL is normal and acceptable — the device floor wins |64| Below ~35 CPL | Real defect: too many line-returns, ragged texture |65| Above ~85 CPL | Real defect regardless of viewport |66| Inside the range | Judge with your eyes; do not tune to hit a count |6768The canon genuinely disagrees here (Lupton 55–70, Rutter 45–75, Material 40–60,69Brown rejecting counting altogether). See `../type/references/corpus-conflicts.md`.70Field trick (Walton, via Stocks): put an asterisk before the 45th character and71after the 75th, then see where lines actually break.7273**Size.** Start from the browser default (commonly 16px) as a *starting point, not74an optimum*. Then adjust for apparent size: a face with a tall x-height at 16px75reads larger than one with a short x-height at the same value. Match apparent76size, not nominal size, when swapping typefaces.7778**Line-height.** 1.3–1.7 unitless for body text is the working range (Latin);79Santa Maria's range is close but wider, 1.2–1.8, and she's explicit that "a true80ideal line-height doesn't exist" — the typeface's design (wide/decorative faces81want more air) and the specific setting (a narrow hanging caption can run tighter82than the article beside it) both move the number, so treat any range as a83starting point to trial against the real typeface, not a value to look up. Push84higher as measure lengthens — a long line needs more vertical separation for85the return sweep to land correctly. Push lower as measure shortens. Tighter than861.3 for a full paragraph is almost always wrong. Always use a **unitless** value so87it inherits proportionally.8889**Don't ship the default leading.** Elam's observation about how designers actually90work: "initially, many designers are satisfied with the computer default values for91leading, about 20% of the text size" — i.e. roughly 1.2 — and the discipline is to92"become sensitive to the texture of the text on the page," then investigate leading93deliberately and "experiment with dense and airy text." A 1.2 line-height in a94paragraph is usually a default nobody chose. See `microtypography` on typographic95colour for reading that texture.9697**Reading distance** scales everything. Kiosk and TV need far larger sizes than98their "equivalent" desktop values. To evaluate this honestly rather than guess,99Brown's technique: zoom the rendered composition to simulate the actual viewing100distance (or better, view it on a real device at its real distance — phone in101hand, TV across a room) and re-judge size and measure at that simulated102closeness, not at your editor's default zoom level.103104## 5. Failure patterns105106| Pattern | Cause | Fix |107|---|---|---|108| Reader loses their place mid-paragraph | Measure too long for the line-height | Shorten measure or increase line-height |109| Text feels dense and airless | Line-height too tight, or x-height tall with tight spacing | Raise line-height; check letter spacing |110| Lines drift apart, paragraph stops cohering | Line-height too large for the measure | Reduce line-height or lengthen measure |111| Fine on desktop, cramped on phone | Fixed px sizing, no fluid strategy | Route to `responsive-typography` |112| Breaks when the user zooms or applies a spacing override | Fixed heights, `overflow: hidden`, absolute positioning | Route to `typography-accessibility` |113| Swapping the font changed the whole page rhythm | Matched nominal size instead of apparent size | Re-tune size to x-height, then re-check measure |114115## 6. Evaluation procedure116117Run in order. Stop and fix before continuing.1181191. **Render it.** Never evaluate body text from CSS alone.1202. Count characters on 3 representative full lines. Compare against the121 diagnostic range for that viewport.1223. Read one full paragraph at real size and distance. Did your eye return123 cleanly on every line?1244. Set `line-height: 1.5`, `word-spacing: .16em`, `letter-spacing: .12em`,125 paragraph spacing `2em`. Confirm nothing clips, overlaps, or disappears126 (WCAG 1.4.12).1275. Zoom to 200%. Confirm no loss of content or function (WCAG 1.4.4).1286. Check the narrowest and widest supported viewport.1297. Check contrast ≥ 4.5:1 for normal text (WCAG 1.4.3).130131## 7. Output format132133```134Setting: <typeface> <size> / <line-height> at <measure>135Inputs: x-height <tall|moderate|short>, device <…>, distance <…>, content <…>136Measure: <N> CPL at <viewport> — <inside|below|above> diagnostic range137Checks: 1.4.12 <pass/fail> · 1.4.4 <pass/fail> · 1.4.3 <ratio>138Conflicts resolved: <which rule won, if any>139Unverified: <anything not checked in a rendered context>140```141142## 8. Examples143144**Documentation site, desktop-first, Source Sans (moderate x-height).**145146> Starting at the 16px browser default. Source Sans has a moderate x-height, so147> apparent size is close to nominal — no compensation needed. At a 68ch column the148> measure lands ~70 CPL, inside range. Line-height 1.6 unitless, toward the upper149> end because the measure is long. Verified at 200% zoom and under a 1.5150> line-height override: no clipping.151152**Swapping Georgia → Merriweather in an existing article template.**153154> Merriweather has a notably larger x-height, so at the same 18px it reads155> distinctly larger and the existing 66ch measure now runs ~74 CPL. Two options:156> drop to 17px to match apparent size and preserve the measure, or keep 18px and157> narrow the column. Recommending the size drop — it preserves the tuned measure158> and the page rhythm.159160## 9. Counterexamples161162- ❌ "Body text should be 16px with 1.5 line-height." — A universal constant with163 no inputs. Wrong for a kiosk, a phone, a TV, or any face with an unusual164 x-height.165- ❌ "Use a serif for body text because serifs are more readable." — Unevidenced.166 Lupton is explicit that research has failed to demonstrate this.167- ❌ "Measure is 45–75 characters, so I set it to exactly 60ch." — `ch` is the168 width of the `0` glyph and varies per font; and tuning to hit a count produces169 the stiff layouts Brown warns about.170- ❌ "It passes contrast, so the body text is accessible." — 1.4.3 is one of three171 relevant criteria; 1.4.4 and 1.4.12 are independent.172- ❌ Setting `line-height: 24px`. Fixed units break inheritance and user scaling.173174## 10. Source citations175176- Hochuli, *Detail in Typography* — the reading process; saccades, fixation177 duration, regression saccades. **Primary source for why any of this matters.**178- Lupton, *Thinking with Type* 3e — measure 55–70; serif readability research is179 inconclusive; familiarity bias.180- Rutter, *Web Typography* — 45–75 range; 42 CPL satisfactory; ~40 CPL on a181 phone at default size; apparent size and x-height compensation.182- Brown, *Flexible Typesetting* — measure as a visual decision; Frere-Jones,183 "we read with our eyes, not with rulers"; zooming a composition to simulate184 real viewing distance/closeness as an evaluation technique, rather than judging185 size at an editor's default zoom.186- Latin, *Better Web Typography* — 1.3–1.7 line-height; the size/line-height/187 measure triangle.188- Santa Maria, *On Web Typography* — 1.2–1.8 line-height as a starting range;189 there's no universal ideal, it's set per typeface and per setting (a narrow190 hanging caption legitimately tighter than the body beside it).191- Lupton (ed.), *Type on Screen* — 45–75 measure on screen.192- Elam, *Typographic Systems of Design* — default leading of about 20% of text size193 as a starting point designers too readily accept; developing sensitivity to the194 texture of the text; experimenting with dense and airy settings.195- Stocks, *Universal Principles of Typography* — Bringhurst's 66; Material's196 40–60; Walton's asterisk trick.197- WCAG 2.2 §1.4.3, §1.4.4, §1.4.12.