Typography and Readability Standards

1. Font Size and Zoom Support

WCAG Requirement Level Specification Implementation
Resize Text (1.4.4) AA Text can be resized up to 200% without loss of content or functionality Use relative units (rem, em, %)
Reflow (1.4.10) AA Content reflows at 320px width without horizontal scrolling Responsive design with media queries
Text Spacing (1.4.12) AA No loss of content when spacing is adjusted Avoid fixed heights, use min-height
Minimum Base Size Best practice 16px minimum for body text font-size: 16px or 1rem
Zoom Support AA Support browser zoom up to 200% Don't disable user scaling

Example: Zoom and resize support

<!-- Proper meta viewport (allows user zoom) -->
<meta name="viewport" content="width=device-width, initial-scale=1.0">

<!-- NEVER disable zoom (accessibility violation) -->
<!-- BAD: -->
<meta name="viewport" content="user-scalable=no, maximum-scale=1.0">

<!-- Use relative units for font sizes -->
<style>
/* Base font size on html element */
html {
  font-size: 16px; /* Base size for rem calculations */
}

/* Use rem for most text (scales with user preferences) */
body {
  font-size: 1rem; /* 16px by default */
  line-height: 1.5;
}

h1 {
  font-size: 2.5rem; /* 40px at default */
}

h2 {
  font-size: 2rem; /* 32px at default */
}

h3 {
  font-size: 1.5rem; /* 24px at default */
}

p {
  font-size: 1rem; /* 16px at default */
}

small {
  font-size: 0.875rem; /* 14px at default */
}

/* Use em for component-relative sizing */
.button {
  font-size: 1rem;
  padding: 0.5em 1em; /* Scales with button font size */
}

.button--large {
  font-size: 1.25rem;
  padding: 0.5em 1em; /* Proportionally larger */
}

/* Responsive font sizing */
@media (max-width: 768px) {
  html {
    font-size: 14px; /* Smaller base on mobile */
  }
}

@media (min-width: 1200px) {
  html {
    font-size: 18px; /* Larger base on large screens */
  }
}

/* Fluid typography (clamps between min and max) */
h1 {
  font-size: clamp(2rem, 5vw, 3rem);
}

/* Support text spacing adjustments (WCAG 1.4.12) */
* {
  /* Don't set fixed heights that break with spacing changes */
  /* Use min-height instead of height when possible */
}

.card {
  min-height: 200px; /* Not height: 200px */
  padding: 1rem;
}

/* Text should reflow without horizontal scroll at 320px */
.content {
  max-width: 100%;
  overflow-wrap: break-word;
  word-wrap: break-word;
}
</style>
Unit Type Description Use Case Accessibility
rem Relative to root font-size Most text, spacing, layout ✓ Respects user preferences
em Relative to parent font-size Component-scoped sizing, padding ✓ Respects user preferences
% (percentage) Relative to parent Widths, responsive layouts ✓ Flexible
px (pixels) Absolute unit Borders, shadows, small details ⚠ Doesn't scale with zoom
vw/vh Viewport percentage Full-screen sections, fluid type ⚠ Can cause reflow issues
clamp() Min, preferred, max Fluid typography with bounds ✓ Responsive + bounded
Warning: Never use maximum-scale=1.0 or user-scalable=no in viewport meta tag. This prevents users from zooming and fails WCAG 1.4.4.

2. Line Height and Spacing Guidelines

Spacing Property WCAG 1.4.12 Minimum Recommended CSS Property
Line Height 1.5× font size (paragraphs) 1.5-1.8 line-height: 1.5
Paragraph Spacing 2× font size 1.5-2rem margin-bottom: 1.5rem
Letter Spacing 0.12× font size normal to 0.05em letter-spacing: 0.02em
Word Spacing 0.16× font size normal to 0.1em word-spacing: 0.05em

Example: Accessible spacing implementation

<style>
/* Base typography with accessible spacing */
body {
  font-size: 1rem;
  line-height: 1.6; /* Exceeds 1.5 minimum */
  letter-spacing: 0.01em;
}

/* Paragraph spacing */
p {
  margin-bottom: 1.5rem; /* 2× font size minimum */
  line-height: 1.6;
}

/* Heading spacing */
h1, h2, h3, h4, h5, h6 {
  line-height: 1.3; /* Tighter for headings OK */
  margin-top: 2rem;
  margin-bottom: 1rem;
}

/* Lists with adequate spacing */
ul, ol {
  margin-bottom: 1.5rem;
}

li {
  margin-bottom: 0.5rem;
  line-height: 1.6;
}

/* Dense text (tables, code) can be tighter */
table {
  line-height: 1.4; /* Still readable */
}

code, pre {
  line-height: 1.5;
  letter-spacing: 0;
}

/* Support user text spacing overrides (WCAG 1.4.12) */
/* Users may apply: */
* {
  /* line-height: 1.5 */
  /* letter-spacing: 0.12em */
  /* word-spacing: 0.16em */
  /* paragraph spacing: 2em */
}

/* Ensure content doesn't break when spacing is increased */
.card {
  min-height: fit-content; /* Not fixed height */
  padding: 1rem;
}

.button {
  padding: 0.75em 1.5em;
  min-height: 2.5em; /* Not height: 40px */
}

/* Long-form content optimized for readability */
article p {
  max-width: 65ch; /* 65-75 characters per line */
  line-height: 1.7;
  margin-bottom: 1.5rem;
}

/* Tight spacing exceptions (sparingly) */
.compact-list {
  line-height: 1.4;
}

.compact-list li {
  margin-bottom: 0.25rem;
}
</style>

<!-- Text spacing adjustment test -->
<style>
/* Apply maximum WCAG 1.4.12 spacing to test */
.wcag-spacing-test * {
  line-height: 1.5 !important;
  letter-spacing: 0.12em !important;
  word-spacing: 0.16em !important;
}

.wcag-spacing-test p {
  margin-bottom: 2em !important;
}

/* Content should remain readable and not clip */
</style>
Content Type Line Height Max Line Length Rationale
Body Text 1.5-1.8 65-75 characters Optimal reading comfort
Headings 1.2-1.4 40-50 characters Tighter for visual hierarchy
Captions 1.4-1.6 55-65 characters Small text needs more spacing
Code Blocks 1.5-1.6 80-120 characters Monospace allows longer lines
Tables 1.4-1.5 Varies by column Denser spacing acceptable
UI Labels 1.3-1.5 N/A Compact for interface elements
Note: The 65-75 character line length guideline is based on readability research. Use max-width: 65ch to implement this in CSS (1ch = width of the "0" character in the current font).

3. Text Scaling and Responsive Typography

Technique Method Benefits Considerations
Fluid Typography clamp(min, preferred, max) Smooth scaling between breakpoints Ensure minimum meets WCAG
Viewport-Based font-size: calc(1rem + 1vw) Scales with viewport Can be too small/large at extremes
Media Query Steps Different sizes per breakpoint Precise control at each size Sudden jumps between breakpoints
Container Queries Size based on container width Component-level responsiveness Newer browser support
User Preference Respect browser font-size setting User control, accessibility Must use relative units

Example: Responsive typography strategies

<style>
/* Strategy 1: Fluid typography with clamp() */
h1 {
  font-size: clamp(1.75rem, 4vw + 1rem, 3.5rem);
  /* Min: 28px, Scales with viewport, Max: 56px */
}

h2 {
  font-size: clamp(1.5rem, 3vw + 0.5rem, 2.5rem);
}

p {
  font-size: clamp(1rem, 0.5vw + 0.875rem, 1.125rem);
}

/* Strategy 2: Media query steps */
body {
  font-size: 16px;
}

@media (max-width: 480px) {
  body { font-size: 14px; }
  h1 { font-size: 1.75rem; }
}

@media (min-width: 481px) and (max-width: 768px) {
  body { font-size: 15px; }
  h1 { font-size: 2rem; }
}

@media (min-width: 769px) and (max-width: 1024px) {
  body { font-size: 16px; }
  h1 { font-size: 2.5rem; }
}

@media (min-width: 1025px) {
  body { font-size: 18px; }
  h1 { font-size: 3rem; }
}

/* Strategy 3: Viewport-based with bounds */
h1 {
  font-size: calc(1.5rem + 2vw);
  max-font-size: 4rem;
  min-font-size: 2rem; /* Note: not a real property, use clamp */
}

/* Better: using clamp for the same effect */
h1 {
  font-size: clamp(2rem, 1.5rem + 2vw, 4rem);
}

/* Strategy 4: Container queries (modern browsers) */
@container (min-width: 400px) {
  .card h2 {
    font-size: 1.5rem;
  }
}

@container (min-width: 600px) {
  .card h2 {
    font-size: 2rem;
  }
}

/* Strategy 5: Modular scale */
:root {
  --ratio: 1.25; /* Major third */
  --base-size: 1rem;
  
  --text-xs: calc(var(--base-size) / var(--ratio) / var(--ratio));
  --text-sm: calc(var(--base-size) / var(--ratio));
  --text-base: var(--base-size);
  --text-lg: calc(var(--base-size) * var(--ratio));
  --text-xl: calc(var(--base-size) * var(--ratio) * var(--ratio));
  --text-2xl: calc(var(--base-size) * var(--ratio) * var(--ratio) * var(--ratio));
}

small { font-size: var(--text-sm); }
body { font-size: var(--text-base); }
h3 { font-size: var(--text-lg); }
h2 { font-size: var(--text-xl); }
h1 { font-size: var(--text-2xl); }

/* Responsive adjustments to base size */
@media (max-width: 768px) {
  :root {
    --base-size: 0.875rem; /* 14px */
  }
}

@media (min-width: 1200px) {
  :root {
    --base-size: 1.125rem; /* 18px */
  }
}

/* Ensure minimum sizes at all breakpoints */
@media (max-width: 480px) {
  body {
    font-size: max(16px, 1rem); /* Never below 16px */
  }
}
</style>

Example: Accessible responsive typography system

<style>
/* Complete responsive type system */
:root {
  /* Base sizes */
  --font-size-min: 0.875rem; /* 14px */
  --font-size-base: 1rem;    /* 16px */
  --font-size-max: 1.125rem; /* 18px */
  
  /* Fluid size between 320px and 1200px viewport */
  --fluid-min-width: 320;
  --fluid-max-width: 1200;
  
  /* Calculate fluid type */
  --fluid-bp: calc(
    (100vw - var(--fluid-min-width) * 1px) / 
    (var(--fluid-max-width) - var(--fluid-min-width))
  );
}

/* Fluid body text */
body {
  font-size: calc(
    var(--font-size-min) + 
    (var(--font-size-max) - var(--font-size-min)) * var(--fluid-bp)
  );
  line-height: 1.6;
}

/* Simplified with clamp() */
body {
  font-size: clamp(
    var(--font-size-min),
    0.875rem + 0.25vw,
    var(--font-size-max)
  );
}

/* Heading scale */
h1 { font-size: clamp(2rem, 1.5rem + 2vw, 3.5rem); }
h2 { font-size: clamp(1.75rem, 1.25rem + 1.5vw, 2.75rem); }
h3 { font-size: clamp(1.5rem, 1rem + 1vw, 2rem); }
h4 { font-size: clamp(1.25rem, 0.875rem + 0.75vw, 1.5rem); }
h5 { font-size: clamp(1.125rem, 0.875rem + 0.5vw, 1.25rem); }
h6 { font-size: clamp(1rem, 0.875rem + 0.25vw, 1.125rem); }

/* Ensure accessibility: never go below minimums */
@supports not (font-size: clamp(1rem, 1vw, 2rem)) {
  /* Fallback for older browsers */
  body { font-size: 16px; }
  h1 { font-size: 2.5rem; }
  h2 { font-size: 2rem; }
  /* etc... */
}
</style>
Warning: When using viewport units (vw, vh), always use clamp() or max() to ensure text doesn't become too small on narrow viewports, which would fail WCAG 1.4.4.

4. Reading Flow and Text Layout

Layout Principle Specification Benefits Implementation
Line Length 50-75 characters optimal Reduces eye fatigue, improves comprehension max-width: 65ch
Text Alignment Left-aligned for LTR languages Consistent left edge aids tracking text-align: left
Justified Text Avoid or use with hyphenation Prevents uneven spacing hyphens: auto if justified
Column Width Single column on mobile, multi on desktop Appropriate line length at all sizes columns or grid layout
Orphans/Widows Prevent single lines at breaks Visual continuity orphans: 2; widows: 2
Vertical Rhythm Consistent spacing between elements Visual harmony, scanability Baseline grid or spacing scale

Example: Optimal reading flow layout

<style>
/* Article layout optimized for readability */
article {
  max-width: 65ch; /* 50-75 character line length */
  margin: 0 auto;
  padding: 2rem 1rem;
}

/* Long-form text styling */
article p {
  text-align: left; /* Never center long text */
  line-height: 1.7;
  margin-bottom: 1.5rem;
  
  /* Prevent orphans and widows */
  orphans: 2;
  widows: 2;
  
  /* Better word breaking */
  overflow-wrap: break-word;
  word-wrap: break-word;
  hyphens: auto; /* Enable hyphenation */
}

/* Avoid justified text or improve it */
.justified {
  text-align: justify;
  hyphens: auto; /* Required for even spacing */
  text-justify: inter-word; /* Better spacing algorithm */
}

/* Multi-column layout (use carefully) */
@media (min-width: 900px) {
  .multi-column {
    column-count: 2;
    column-gap: 3rem;
    column-rule: 1px solid #e0e0e0;
  }
  
  /* Prevent headings from breaking across columns */
  .multi-column h2,
  .multi-column h3 {
    break-after: avoid;
    column-span: all; /* Heading spans all columns */
  }
  
  /* Prevent images from breaking */
  .multi-column img {
    break-inside: avoid;
  }
}

/* Responsive line length */
.content {
  width: 100%;
  max-width: 65ch;
}

@media (max-width: 768px) {
  .content {
    max-width: 100%; /* Full width on mobile */
    padding: 0 1rem;
  }
}

/* Vertical rhythm system */
:root {
  --line-height: 1.6;
  --rhythm: calc(1rem * var(--line-height));
}

h1, h2, h3, p, ul, ol {
  margin-bottom: var(--rhythm);
}

/* Lists with proper spacing */
ul, ol {
  padding-left: 1.5rem;
}

li {
  margin-bottom: 0.5rem;
  line-height: 1.6;
}

/* Pull quotes or callouts */
.callout {
  max-width: 45ch; /* Shorter for emphasis */
  margin: 2rem auto;
  padding: 1.5rem;
  font-size: 1.125rem;
  border-left: 4px solid #0066cc;
}

/* Code blocks with scrolling instead of wrapping */
pre {
  max-width: 100%;
  overflow-x: auto;
  padding: 1rem;
  line-height: 1.5;
}

/* Prevent very long words from breaking layout */
.user-content {
  overflow-wrap: break-word;
  word-wrap: break-word;
  word-break: break-word; /* Breaks long words */
}

/* Direction support for RTL languages */
[dir="rtl"] {
  text-align: right;
}

[dir="rtl"] ul,
[dir="rtl"] ol {
  padding-left: 0;
  padding-right: 1.5rem;
}
</style>

<article lang="en">
  <h1>Article Title</h1>
  <p>
    This paragraph has an optimal line length of around 65 characters,
    which research shows provides the best reading experience. The text
    is left-aligned with adequate line height for easy tracking.
  </p>
  <p>
    Long form content should never be centered or right-aligned as this
    makes it difficult for readers to find the start of each new line.
  </p>
</article>
Note: Centered or right-aligned text is acceptable for short content like headings, captions, or UI elements, but long-form body text should always be left-aligned (or right-aligned for RTL languages).

5. Font Selection for Accessibility

Font Characteristic Accessible Choice Avoid Why
Letter Differentiation Clear distinction between I, l, 1, O, 0 Fonts where letters look identical Reduces confusion for dyslexic users
X-Height Larger x-height (relative to cap height) Very small x-height Improves readability at small sizes
Weight Variation Multiple weights available Single weight only Needed for hierarchy and emphasis
Character Spacing Slightly open spacing Very tight or condensed Easier to distinguish letters
Decorative Features Minimal for body text Excessive serifs, swashes, ornaments Can distract or confuse readers
Font Style Sans-serif for UI, serif OK for long text Script, handwriting, novelty fonts Novelty fonts harder to read

Example: Accessible font selection

<style>
/* Accessible font stacks */

/* System font stack (no web fonts needed, fast) */
body {
  font-family: 
    system-ui,
    -apple-system,
    BlinkMacSystemFont,
    "Segoe UI",
    Roboto,
    "Helvetica Neue",
    Arial,
    sans-serif;
}

/* Readable serif stack for long-form content */
article {
  font-family:
    "Iowan Old Style",
    "Palatino Linotype",
    "URW Palladio L",
    Georgia,
    serif;
}

/* Monospace stack for code */
code, pre {
  font-family:
    "SF Mono",
    Monaco,
    "Cascadia Code",
    "Roboto Mono",
    Consolas,
    "Courier New",
    monospace;
}

/* Web fonts with careful selection */
@font-face {
  font-family: 'CustomFont';
  src: url('font.woff2') format('woff2');
  font-display: swap; /* Show fallback during load */
  font-weight: 400;
  font-style: normal;
}

/* Use variable fonts for performance */
@font-face {
  font-family: 'InterVariable';
  src: url('inter-variable.woff2') format('woff2');
  font-weight: 100 900; /* Supports all weights */
  font-display: swap;
}

/* Accessible fonts recommended: */
/* - Inter (excellent readability) */
/* - Atkinson Hyperlegible (designed for low vision) */
/* - Open Sans, Roboto (good alternatives) */
/* - Lexend (dyslexia-friendly) */

/* Font adjustments for accessibility */
body {
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-rendering: optimizeLegibility;
}

/* Never use ultra-thin weights for body text */
.thin-text {
  font-weight: 100; /* BAD for accessibility */
}

.readable-text {
  font-weight: 400; /* GOOD: normal weight */
}

/* Italic text - use sparingly */
em, i {
  font-style: italic;
  /* Some fonts have poor italics - consider checking */
}

/* All caps - harder to read, use sparingly */
.uppercase {
  text-transform: uppercase;
  letter-spacing: 0.05em; /* Increase spacing */
  font-size: 0.875em; /* Slightly smaller often better */
}

/* Font size adjustments */
small {
  font-size: 0.875rem; /* Don't go below 14px equivalent */
}

/* Ensure minimum legible sizes */
@media (max-width: 768px) {
  small {
    font-size: max(0.875rem, 14px);
  }
}
</style>

<!-- Example: Dyslexia-friendly font -->
<link href="https://fonts.googleapis.com/css2?family=Lexend:wght@400;600&display=swap" rel="stylesheet">

<style>
.dyslexia-friendly {
  font-family: 'Lexend', sans-serif;
  font-size: 1.125rem; /* Slightly larger */
  line-height: 1.8; /* More spacing */
  letter-spacing: 0.05em;
  word-spacing: 0.1em;
}
</style>
Font Family Type Accessibility Features Best Use
Atkinson Hyperlegible Sans-serif Designed for low vision, high differentiation UI, body text, low vision users
Inter Sans-serif Tall x-height, open apertures UI, screens, body text
Lexend Sans-serif Designed for dyslexia Body text, educational content
Open Dyslexic Sans-serif Weighted bottoms, unique shapes Dyslexic users (optional)
Verdana Sans-serif Large x-height, wide spacing Small sizes, screens
Georgia Serif Large characters, screen-optimized Long-form reading
Comic Sans Sans-serif Letter differentiation (controversial) Dyslexic users (user preference)
Warning: Avoid using font weights below 400 for body text, and never use decorative or script fonts for important content. They can be difficult or impossible for some users to read.
Note: Consider providing a font switcher for users with dyslexia or low vision. Allow users to choose between standard fonts and specialized alternatives like Lexend or OpenDyslexic.

Typography and Readability Quick Reference

  • Use relative units (rem, em) for all font sizes - never disable zoom with viewport meta
  • Minimum 16px base font size; text must be resizable to 200% without loss of content
  • Line height minimum 1.5 for body text; paragraph spacing minimum 2× font size (WCAG 1.4.12)
  • Optimal line length: 50-75 characters (use max-width: 65ch)
  • Left-align body text (right-align for RTL); avoid justified text unless using hyphenation
  • Use clamp() for fluid typography with minimum/maximum bounds
  • Choose fonts with clear letter differentiation (I/l/1, O/0) and adequate x-height
  • Provide font weight variation (400 minimum for body text; avoid ultra-thin weights)
  • Test spacing with WCAG 1.4.12 adjustments: content must not clip or overlap
  • Consider specialized fonts (Atkinson Hyperlegible, Lexend) for improved accessibility