Design typography that is readable by users with dyslexia, low vision, and cognitive disabilities — appropriate reading level, line height, letter spacing, and zoom-responsive text.
Design typography that is readable by users with dyslexia, low vision, and cognitive disabilities — appropriate reading level, line height, letter spacing, and responsive text.
WCAG 1.4.8 (Visual Presentation, Level AAA) specifies recommendations for optimal reading. While AAA, these are worth implementing at AA level for user experience:
WCAG 1.4.12 (Text Spacing, Level AA): Changing text spacing to specific values must not cause loss of content or functionality. The text spacing bookmarklet tests this by applying:
1/* WCAG 1.4.12 test values */
2* {
3 line-height: 1.5 !important;
4 letter-spacing: 0.12em !important;
5 word-spacing: 0.16em !important;
6}
7p {
8 margin-bottom: 2em !important;
9}If your layout breaks when these values are applied (text overflows, elements overlap, content is hidden), it fails WCAG 1.4.12.
Font selection significantly impacts readability for users with dyslexia and low vision:
1/* System font stack: uses the OS's default accessible font */
2:root {
3 --font-family-body:
4 -apple-system, /* iOS/macOS San Francisco */
5 BlinkMacSystemFont, /* Chrome on macOS */
6 'Segoe UI', /* Windows */
7 Roboto, /* Android */
8 'Helvetica Neue', sans-serif;
9
10 /* Minimum readable body size: 16px (1rem) */
11 --font-size-body: 1rem;
12
13 /* Line height: 1.5 for body text */
14 --line-height-body: 1.5;
15
16 /* Optimum line width: 60-80 characters */
17 --text-measure: 65ch;
18}
19
20body {
21 font-family: var(--font-family-body);
22 font-size: var(--font-size-body);
23 line-height: var(--line-height-body);
24}
25
26/* Constrain line length for readability */
27.prose, .article-body, .documentation {
28 max-width: var(--text-measure);
29}For users with dyslexia, certain fonts (OpenDyslexic, Lexie Readable, Atkinson Hyperlegible) are specifically designed with differentiated letterforms (b/d/p/q look distinctly different). If your audience includes many users with dyslexia, consider offering a font preference setting:
1<select
2 aria-label="Font preference"
3 onChange={e => setUserFont(e.target.value)}
4>
5 <option value="default">Default (System font)</option>
6 <option value="opendyslexic">OpenDyslexic</option>
7 <option value="atkinson">Atkinson Hyperlegible</option>
8</select>WCAG 1.4.4 (Resize Text, Level AA) requires text to be resizable to 200% without loss of content or functionality. WCAG 1.4.10 (Reflow, Level AA) requires content to reflow to a single column at 320px (equivalent to 400% zoom on a 1280px browser). Implement with fluid typography and container-aware layouts:
1/* Fluid typography: scales with viewport, bounded by min/max */
2:root {
3 /* Body text: 16px on mobile, 18px on desktop */
4 --font-size-body: clamp(1rem, 0.875rem + 0.5vw, 1.125rem);
5
6 /* Headings: scale without becoming too large or small */
7 --font-size-h1: clamp(1.75rem, 1.5rem + 1.5vw, 3rem);
8 --font-size-h2: clamp(1.5rem, 1.25rem + 1vw, 2.25rem);
9}
10
11/* Never lock text size to viewport units without a minimum */
12/* BAD: 2vw is unreadable at small viewports */
13h1 { font-size: 2vw; }
14
15/* GOOD: clamp ensures minimum legible size */
16h1 { font-size: var(--font-size-h1); }
17
18/* Reflow at 320px: no horizontal overflow */
19body {
20 max-width: 100%;
21 overflow-x: hidden;
22}
23
24.container {
25 /* Use padding instead of fixed margins that create horizontal scroll */
26 padding-inline: clamp(1rem, 5vw, 3rem);
27 max-width: 75ch;
28 margin-inline: auto;
29}
30
31/* Data tables that can't reflow: provide horizontal scroll with keyboard support */
32.table-wrapper {
33 overflow-x: auto;
34 /* Keyboard-scrollable: add tabIndex if no other focusable children */
35 tabindex: 0;
36}WCAG 1.4.12 requires that user-applied text spacing overrides do not break your layout. Test by running the WCAG Text Spacing bookmarklet on every key page and verifying no content is hidden or overlapping:
1/* Patterns that BREAK under text spacing overrides */
2
3/* BAD: Fixed height container clips expanded text */
4.card { height: 120px; overflow: hidden; }
5
6/* BAD: Absolute positioned label that does not resize with parent */
7.form-field { position: relative; height: 48px; }
8.form-field label { position: absolute; top: 14px; }
9
10/* BAD: Tight line-height that causes text overlap when overridden */
11.compact-list li { line-height: 1.1; }
12
13/* GOOD patterns for text spacing compatibility */
14
15/* Use min-height instead of height */
16.card { min-height: 120px; }
17
18/* Use min-height on form fields */
19.form-field { min-height: 48px; }
20
21/* Allow line-height to expand */
22.compact-list li { line-height: 1.4; }
23
24/* Avoid overflow: hidden that clips text */
25.truncated-text {
26 /* White-space nowrap + overflow hidden + text-overflow ellipsis
27 is the only acceptable use of overflow hidden on text */
28 white-space: nowrap;
29 overflow: hidden;
30 text-overflow: ellipsis;
31 /* But: truncated text must be fully accessible via another mechanism
32 (expanded on click, available in a tooltip with full text) */
33}WCAG 3.1.5 (Reading Level, Level AAA) recommends content be readable at the lower secondary education level (around grade 8). While AAA, plain language is a core cognitive accessibility practice:
1// Measure reading level with the Flesch-Kincaid formula
2function measureReadingLevel(text: string): number {
3 const sentences = text.split(/[.!?]+/).filter(Boolean).length;
4 const words = text.split(/\s+/).filter(Boolean).length;
5 const syllables = text.split(/\s+/).reduce((count, word) =>
6 count + countSyllables(word), 0
7 );
8
9 // Flesch-Kincaid Grade Level
10 const gradeLevel =
11 0.39 * (words / sentences) +
12 11.8 * (syllables / words) - 15.59;
13
14 return Math.round(gradeLevel * 10) / 10;
15}
16
17// Run in CI to flag high reading-level content
18const content = getPageContent(url);
19const grade = measureReadingLevel(content);
20if (grade > 10) {
21 console.warn(`Reading level: Grade ${grade} (target: Grade 8 or below)`);
22}Practical plain language rules that reduce reading level:
Run the WCAG Text Spacing bookmarklet on your product's main page. Note every element where content is hidden or overlapping. Fix the top 3 violations by replacing fixed heights with min-heights.
Your progress is saved in this browser, on this device only.