Skip to main content

WCAG Reference

Web Content Accessibility Guidelines (WCAG) 2.1 are the international standard for web accessibility. These guidelines ensure content is accessible to people with disabilities.

POUR Principles

WCAG is organized around four principles:
PrincipleDescription
PerceivableInformation and UI components must be presentable to users in ways they can perceive
OperableUI components and navigation must be operable by all users
UnderstandableInformation and operation of UI must be understandable
RobustContent must be robust enough to be interpreted by a wide variety of user agents, including assistive technologies

Conformance Levels

LevelDescriptionRequirementLegal Status
ABasic accessibility featuresMinimumRequired by most laws
AAAddresses major accessibility barriersStandardRequired by ADA, Section 508, EU standards
AAAHighest level of accessibilityEnhancedRecommended but not always achievable
Target: AA compliance at minimum

Success Criteria by Level

Level A (Minimum)

Perceivable

1.1.1 Non-text Content
  • All images, icons have text alternatives
  • Decorative images use empty alt text
<!-- Informative image -->
<img src="chart.png" alt="Sales increased 40% in Q3">

<!-- Decorative image -->
<img src="border.png" alt="" role="presentation">
1.2.1 Audio-only and Video-only
  • Provide transcript for audio
  • Provide audio description or transcript for video
1.2.2 Captions (Prerecorded)
  • Captions provided for all prerecorded audio in video
1.2.3 Audio Description or Media Alternative
  • Audio description or transcript for prerecorded video
1.3.1 Info and Relationships
  • Information, structure, and relationships conveyed through presentation can be programmatically determined
<!-- Use semantic HTML -->
<table>
  <thead>
    <tr>
      <th>Header</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Data</td>
    </tr>
  </tbody>
</table>
1.3.2 Meaningful Sequence
  • Reading order is logical
1.3.3 Sensory Characteristics
  • Instructions don’t rely solely on shape, size, visual location, orientation, or sound
1.4.1 Use of Color
  • Color is not the only visual means of conveying information
<!-- Bad: Only color indicates error -->
<input style="border: 2px solid red">

<!-- Good: Icon + text + color -->
<input aria-invalid="true" aria-describedby="error">
<span id="error" class="error">
  <svg aria-hidden="true"><!-- error icon --></svg>
  Invalid email format
</span>
1.4.2 Audio Control
  • Audio playing automatically for more than 3 seconds has a control to pause/stop

Operable

2.1.1 Keyboard
  • All functionality available via keyboard
2.1.2 No Keyboard Trap
  • Keyboard focus can be moved away from any component
2.1.4 Character Key Shortcuts
  • Single-key shortcuts can be turned off, remapped, or only active on focus
2.2.1 Timing Adjustable
  • User can turn off, adjust, or extend time limits
2.2.2 Pause, Stop, Hide
  • Moving, blinking, scrolling, or auto-updating content can be paused
2.3.1 Three Flashes or Below Threshold
  • No content flashes more than 3 times per second
2.4.1 Bypass Blocks
  • Mechanism to bypass repeated blocks of content
<a href="#main-content" class="skip-link">Skip to main content</a>
2.4.2 Page Titled
  • Web pages have descriptive titles
2.4.3 Focus Order
  • Focus order is logical and preserves meaning
2.4.4 Link Purpose (In Context)
  • Purpose of each link is clear from link text or context
2.5.1 Pointer Gestures
  • Multi-point or path-based gestures have single-pointer alternative
2.5.2 Pointer Cancellation
  • Functions triggered on down-event can be aborted or undone
2.5.3 Label in Name
  • Visible label text is part of accessible name
2.5.4 Motion Actuation
  • Functions triggered by motion have UI alternative

Understandable

3.1.1 Language of Page
  • Default language of page is programmatically determined
<html lang="en">
3.2.1 On Focus
  • Receiving focus doesn’t trigger unexpected context change
3.2.2 On Input
  • Changing setting doesn’t automatically cause context change
3.3.1 Error Identification
  • Input errors are identified and described in text
3.3.2 Labels or Instructions
  • Labels or instructions provided for user input
<label for="email">Email address</label>
<input type="email" id="email" required>

Robust

4.1.1 Parsing
  • HTML is well-formed (no duplicate IDs, proper nesting)
4.1.2 Name, Role, Value
  • All UI components have accessible name, role, and state

Level AA (Standard)

Perceivable

1.2.4 Captions (Live)
  • Live audio content has captions
1.2.5 Audio Description (Prerecorded)
  • Audio description provided for all prerecorded video
1.3.4 Orientation
  • Content doesn’t restrict view to single orientation (portrait/landscape)
1.3.5 Identify Input Purpose
  • Purpose of input fields can be programmatically determined
<input type="email" autocomplete="email">
1.4.3 Contrast (Minimum)
  • Text has minimum 4.5:1 contrast ratio
  • Large text (18px+ or 14px+ bold) has 3:1 ratio
Text SizeMinimum Contrast
Normal (< 18px)4.5:1
Large (≥ 18px or ≥ 14px bold)3:1
UI components3:1
1.4.4 Resize Text
  • Text can be resized to 200% without loss of content or functionality
1.4.5 Images of Text
  • Use actual text instead of images of text (except logos)
1.4.10 Reflow
  • Content reflows at 320px width without horizontal scrolling
1.4.11 Non-text Contrast
  • UI components and graphical objects have 3:1 contrast
1.4.12 Text Spacing
  • Content adapts when users adjust text spacing
1.4.13 Content on Hover or Focus
  • Additional content triggered by hover/focus is dismissible, hoverable, persistent

Operable

2.4.5 Multiple Ways
  • More than one way to find pages (navigation, search, sitemap)
2.4.6 Headings and Labels
  • Headings and labels describe topic or purpose
2.4.7 Focus Visible
  • Keyboard focus indicator is visible
:focus-visible {
  outline: 2px solid #005fcc;
  outline-offset: 2px;
}

Understandable

3.1.2 Language of Parts
  • Language changes within page are marked
<p>The French word for hello is <span lang="fr">bonjour</span>.</p>
3.2.3 Consistent Navigation
  • Navigation is consistent across pages
3.2.4 Consistent Identification
  • Components with same functionality use same labels
3.3.3 Error Suggestion
  • Input error corrections are suggested when known
3.3.4 Error Prevention (Legal, Financial, Data)
  • Submissions are reversible, verified, or confirmed

Robust

4.1.3 Status Messages
  • Status messages announced to assistive technologies
<div role="status" aria-live="polite">
  Item added to cart
</div>

Level AAA (Enhanced)

Key AAA Criteria

1.4.6 Contrast (Enhanced)
  • 7:1 for normal text, 4.5:1 for large text
1.4.9 Images of Text (No Exception)
  • No images of text (except essential uses)
2.1.3 Keyboard (No Exception)
  • All functionality keyboard accessible without timing exceptions
2.2.3 No Timing
  • No time limits on content
2.4.9 Link Purpose (Link Only)
  • Link purpose determined from link text alone
2.4.10 Section Headings
  • Section headings organize content
3.1.5 Reading Level
  • Alternative content provided for text requiring advanced reading ability
3.3.6 Error Prevention (All)
  • All user submissions are reversible, verified, or confirmed

Common ARIA Patterns

Buttons

<!-- Native button (preferred) -->
<button>Label</button>

<!-- Icon button -->
<button aria-label="Close dialog">×</button>
<!-- Descriptive link text -->
<a href="/products">View all products</a>

<!-- External link -->
<a href="https://external.com" target="_blank" rel="noopener">
  External site
  <span class="visually-hidden">(opens in new tab)</span>
</a>

Form Fields

<label for="email">Email address</label>
<input type="email" id="email" 
       aria-describedby="email-hint"
       autocomplete="email">
<p id="email-hint">We'll never share your email.</p>

Error States

<label for="email">Email</label>
<input type="email" id="email" 
       aria-invalid="true" 
       aria-describedby="email-error">
<p id="email-error" role="alert">
  Please enter a valid email address.
</p>
<nav aria-label="Main">
  <ul>
    <li><a href="/" aria-current="page">Home</a></li>
    <li><a href="/about">About</a></li>
  </ul>
</nav>

Modals

<div role="dialog" 
     aria-modal="true" 
     aria-labelledby="dialog-title"
     aria-describedby="dialog-desc">
  <h2 id="dialog-title">Confirm Action</h2>
  <p id="dialog-desc">Are you sure you want to continue?</p>
  <button>Confirm</button>
  <button>Cancel</button>
</div>

Live Regions

<!-- Polite (waits for pause) -->
<div aria-live="polite">Status update</div>

<!-- Assertive (interrupts) -->
<div aria-live="assertive" role="alert">Error message</div>

<!-- Status (implicit polite) -->
<div role="status">Loading complete</div>

Testing Tools

ToolTypeURL
axe DevToolsBrowser extensiondeque.com/axe
WAVEBrowser extensionwave.webaim.org
LighthouseBuilt into ChromeDevTools → Lighthouse
NVDAScreen reader (Windows)nvaccess.org
VoiceOverScreen reader (Mac)Built into macOS (⌘ + F5)
Colour Contrast AnalyserDesktop apptpgi.com
axe-core CLICommand linenpm install @axe-core/cli -g

Screen Reader Commands

ActionVoiceOver (Mac)NVDA (Windows)
Start/Stop⌘ + F5Ctrl + Alt + N
Next itemVO + →
Previous itemVO + ←
ActivateVO + SpaceEnter
Headings listVO + UH / Shift + H
Links listVO + U, then arrowsK / Shift + K

Testing Checklist

Automated Testing

# Lighthouse accessibility audit
npx lighthouse https://example.com --only-categories=accessibility

# axe-core CLI
npm install @axe-core/cli -g
axe https://example.com

Manual Testing

  • Keyboard navigation: Tab through page, use Enter/Space to activate
  • Screen reader: Test with VoiceOver (Mac) or NVDA (Windows)
  • Zoom: Content usable at 200% zoom
  • High contrast: Test with Windows High Contrast Mode
  • Reduced motion: Test with prefers-reduced-motion: reduce
  • Focus order: Logical and follows visual order
  • Color contrast: Check with Colour Contrast Analyser

Common Issues by Impact

Critical (Fix Immediately)

  1. Missing form labels
  2. Missing image alt text
  3. Insufficient color contrast
  4. Keyboard traps
  5. No focus indicators

Serious (Fix Before Launch)

  1. Missing page language
  2. Missing heading structure
  3. Non-descriptive link text
  4. Auto-playing media
  5. Missing skip links

Moderate (Fix Soon)

  1. Missing ARIA labels on icons
  2. Inconsistent navigation
  3. Missing error identification
  4. Timing without controls
  5. Missing landmark regions

Additional Resources

Build docs developers (and LLMs) love