Web Accessibility Testing Guide: WCAG 2.1 Compliance Checklist
Why Accessibility Testing Matters
Web accessibility ensures that people with disabilities can perceive, understand, navigate, and interact with websites. According to the WHO, over 1 billion people -- about 16% of the global population -- live with some form of disability. Beyond the moral imperative, accessibility is increasingly a legal requirement: ADA lawsuits against websites exceeded 4,600 in 2023, and the European Accessibility Act takes full effect in 2025.
Accessible websites also benefit everyone. Captions help users in noisy environments. High contrast benefits users in bright sunlight. Keyboard navigation is faster for power users. Good semantic HTML improves SEO because search engines parse the same structure that screen readers use.
This guide covers the WCAG 2.1 standard, testing methodologies (automated and manual), essential ARIA patterns, and a practical checklist you can apply to any web project.
WCAG 2.1 Conformance Levels Explained
WCAG organizes its success criteria into three conformance levels. Each level builds on the previous one, adding stricter requirements.
| Level | Criteria | Focus | Legal Target |
|---|---|---|---|
| A | 25 criteria | Basic access: alt text, keyboard, page titles | Minimum baseline |
| AA | 13 additional | Contrast, resize, consistent nav, error handling | Most laws (ADA, Section 508, EAA) |
| AAA | 23 additional | Sign language, enhanced contrast, reading level | Rarely required across entire sites |
Most organizations target WCAG 2.1 Level AA, which covers the majority of accessibility needs. The four foundational principles (POUR) organize all criteria: content must be Perceivable, Operable, Understandable, and Robust.
Automated Testing Tools
Automated tools catch approximately 30-40% of WCAG issues. They excel at structural checks but cannot evaluate subjective quality (like whether alt text is meaningful). Use them as a first pass, never as the only testing method.
| Tool | Type | Best For | Cost |
|---|---|---|---|
| axe-core / axe DevTools | Browser extension + CI | Component-level testing, CI integration | Free (core) / Paid (pro) |
| Lighthouse | Built into Chrome DevTools | Quick audits, performance + a11y | Free |
| WAVE | Browser extension + web | Visual overlay showing issues in context | Free |
| Pa11y | CLI / CI tool | CI/CD pipelines, bulk testing | Free (open source) |
| eslint-plugin-jsx-a11y | Linter plugin | Catching issues during development | Free |
// axe-core in Playwright tests
import { test, expect } from '@playwright/test';
import AxeBuilder from '@axe-core/playwright';
test('homepage passes axe accessibility checks', async ({ page }) => {
await page.goto('/');
const results = await new AxeBuilder({ page })
.withTags(['wcag2a', 'wcag2aa', 'wcag21aa'])
.analyze();
expect(results.violations).toEqual([]);
});
// Jest + React Testing Library
import { render } from '@testing-library/react';
import { axe, toHaveNoViolations } from 'jest-axe';
expect.extend(toHaveNoViolations);
test('form has no a11y violations', async () => {
const { container } = render(<LoginForm />);
const results = await axe(container);
expect(results).toHaveNoViolations();
});Manual Testing Techniques
Manual testing catches the 60-70% of issues that automated tools miss. Focus on these core techniques:
Keyboard Navigation Testing
Every interactive element must be reachable and operable with keyboard alone. Test these key interactions:
| Key | Expected Behavior |
|---|---|
| Tab | Move focus to next interactive element |
| Shift+Tab | Move focus to previous interactive element |
| Enter | Activate links and buttons |
| Space | Toggle checkboxes, activate buttons |
| Arrow keys | Navigate within widgets (tabs, menus, radio groups) |
| Escape | Close modals, dismiss dropdowns |
Screen Reader Testing
Test with at least one screen reader. NVDA (Windows, free) and VoiceOver (macOS, built-in) are the most common. Verify that headings create a logical outline, images have descriptive alt text, form fields have associated labels, and dynamic content changes are announced.
| Screen Reader | Platform | Browser | Cost |
|---|---|---|---|
| NVDA | Windows | Firefox, Chrome | Free |
| JAWS | Windows | Chrome, Edge | $90/year |
| VoiceOver | macOS / iOS | Safari | Free (built-in) |
| TalkBack | Android | Chrome | Free (built-in) |
Color Contrast Requirements
Insufficient color contrast is the single most common accessibility issue on the web. WCAG defines specific contrast ratio thresholds based on text size and conformance level.
| Element | AA Ratio | AAA Ratio |
|---|---|---|
| Normal text (<18px or <14px bold) | 4.5:1 | 7:1 |
| Large text (18px+ or 14px+ bold) | 3:1 | 4.5:1 |
| UI components and graphical objects | 3:1 | N/A |
| Focus indicators | 3:1 | N/A |
Use BytePane's Color Converter to check contrast ratios between any two colors, or use browser DevTools which shows contrast ratio in the color picker.
ARIA Roles, States, and Properties
ARIA (Accessible Rich Internet Applications) adds semantic information to HTML elements that screen readers use to describe the UI. The first rule of ARIA: do not use ARIA if a native HTML element provides the same semantics.
<!-- BAD: Using ARIA when native HTML works -->
<div role="button" tabindex="0" onclick="submit()">Submit</div>
<!-- GOOD: Native HTML button -->
<button type="submit">Submit</button>
<!-- BAD: ARIA checkbox -->
<div role="checkbox" aria-checked="false" tabindex="0">
Accept terms
</div>
<!-- GOOD: Native checkbox -->
<label>
<input type="checkbox" name="terms" />
Accept terms
</label>When you must use ARIA (for custom widgets with no HTML equivalent), follow these essential patterns:
<!-- Tab component -->
<div role="tablist" aria-label="Settings sections">
<button role="tab" aria-selected="true" aria-controls="panel-1" id="tab-1">
General
</button>
<button role="tab" aria-selected="false" aria-controls="panel-2" id="tab-2">
Security
</button>
</div>
<div role="tabpanel" id="panel-1" aria-labelledby="tab-1">
General settings content...
</div>
<!-- Live regions for dynamic content -->
<div aria-live="polite" aria-atomic="true">
3 results found
</div>
<!-- Modal dialog -->
<div role="dialog" aria-modal="true" aria-labelledby="dialog-title">
<h2 id="dialog-title">Confirm deletion</h2>
<p>This action cannot be undone.</p>
<button>Cancel</button>
<button>Delete</button>
</div>Semantic HTML Checklist
Proper semantic HTML eliminates the need for most ARIA attributes. Screen readers and search engines rely on HTML semantics to understand page structure.
| Element | Use For | Not |
|---|---|---|
| <nav> | Navigation links | <div class="nav"> |
| <main> | Primary page content | <div id="content"> |
| <article> | Self-contained content | <div class="post"> |
| <button> | Clickable actions | <div onclick="..."> |
| <label> | Form field descriptions | <span>Name:</span> |
| <h1>-<h6> | Heading hierarchy | <div class="heading"> |
Common Accessibility Issues and Fixes
1. Missing or Empty Alt Text
<!-- Decorative image: use empty alt -->
<img src="divider.svg" alt="" role="presentation" />
<!-- Informative image: describe the content -->
<img src="chart.png" alt="Bar chart showing 40% increase in sales Q3 2025" />
<!-- Linked image: describe the destination -->
<a href="/dashboard/">
<img src="logo.svg" alt="Return to dashboard" />
</a>2. Missing Form Labels
<!-- BAD: no label association -->
<span>Email</span>
<input type="email" />
<!-- GOOD: explicit label -->
<label for="email">Email</label>
<input type="email" id="email" />
<!-- GOOD: implicit label (wrapping) -->
<label>
Email
<input type="email" />
</label>
<!-- For visually hidden labels -->
<label for="search" class="sr-only">Search</label>
<input type="search" id="search" placeholder="Search..." />3. Focus Management in SPAs
// After route change, move focus to main content
useEffect(() => {
const main = document.querySelector('main');
if (main) {
main.setAttribute('tabindex', '-1');
main.focus();
main.addEventListener('blur', () => {
main.removeAttribute('tabindex');
}, { once: true });
}
}, [pathname]);
// Skip navigation link
<a href="#main-content" className="sr-only focus:not-sr-only
focus:fixed focus:top-0 focus:left-0 focus:z-50
focus:p-4 focus:bg-white focus:text-black">
Skip to main content
</a>WCAG 2.1 Quick-Reference Checklist
Use this checklist for every page or component you build. Items marked with asterisks (*) are the most commonly failed criteria.
Perceivable
- * All images have appropriate alt text (or alt="" for decorative)
- * Color contrast meets 4.5:1 for text, 3:1 for large text
- * Information is not conveyed by color alone
- Videos have captions and audio descriptions
- Content can be resized to 200% without loss of functionality
- Text spacing can be overridden without breaking layout
Operable
- * All functionality is available via keyboard
- * Focus order is logical and visible
- No keyboard traps (user can always Tab away)
- Users can pause, stop, or hide moving content
- No content that flashes more than 3 times per second
- Pages have descriptive titles
- Link purpose is clear from text (avoid "click here")
Understandable
- * Form inputs have visible labels
- * Error messages identify the field and suggest correction
- Page language is set (lang attribute on html)
- Navigation is consistent across pages
- No unexpected context changes on focus or input
Robust
- HTML validates (no duplicate IDs, proper nesting)
- Custom components have correct ARIA roles and states
- Status messages use aria-live regions
Frequently Asked Questions
What is WCAG 2.1 and why does it matter?
WCAG 2.1 (Web Content Accessibility Guidelines) is the international standard for web accessibility published by the W3C. It defines how to make web content accessible to people with disabilities including visual, auditory, motor, and cognitive impairments. Compliance is legally required in many jurisdictions under laws like the ADA, Section 508, and the European Accessibility Act.
What is the difference between WCAG Level A, AA, and AAA?
Level A covers basic accessibility requirements (25 criteria). Level AA adds 13 more criteria covering contrast ratios, resize support, and consistent navigation -- most legal requirements target AA. Level AAA adds 23 criteria for enhanced accessibility but is rarely required as a blanket standard because some content types cannot meet all AAA criteria.
Can automated tools catch all accessibility issues?
No. Automated tools typically catch only 30-40% of WCAG issues. They excel at detecting missing alt text, low contrast ratios, missing form labels, and invalid ARIA attributes. However, they cannot evaluate whether alt text is meaningful, whether focus order is logical, or whether custom widgets are keyboard-operable. Manual testing with screen readers and keyboard navigation is essential.
What are the minimum contrast ratios required by WCAG?
WCAG AA requires a contrast ratio of at least 4.5:1 for normal text (under 18px or 14px bold) and 3:1 for large text (18px+ or 14px+ bold). WCAG AAA raises these to 7:1 and 4.5:1 respectively. UI components and graphical objects require at least 3:1 contrast against adjacent colors.
Test Accessibility with BytePane Tools
Check color contrast ratios with our free Color Converter, validate your HTML structure, and ensure proper heading hierarchy. All tools run in your browser with zero setup.
Open Color ConverterRelated Articles
Color Formats Explained
HEX, RGB, HSL color formats and contrast ratios for design.
CSS Grid vs Flexbox
When to use each layout system for accessible, responsive design.
Web Performance Optimization
Core Web Vitals, loading speed, and user experience optimization.
REST API Design Principles
Best practices for HTTP methods, error handling, and versioning.