Website Accessibility Audit — Lighthouse, axe & WAVE Guide
In this tutorial, you'll learn about Website Accessibility Audit. We cover key concepts, practical examples, and best practices.
A website accessibility audit evaluates how well people with disabilities can use your site — identifying barriers that automated and manual testing can uncover before they exclude real users.
What You'll Learn
Running automated audits with Lighthouse and axe DevTools, manual testing with WAVE and screen readers (NVDA, VoiceOver), understanding WCAG 2.2 success criteria (A, AA, AAA), prioritizing fixes, and building an accessibility-first development pipeline.
Why It Matters
15% of the world's population experiences some form of disability. Inaccessible websites are not just exclusionary — they're illegal in many jurisdictions (ADA, Section 508, EN 301 549). Accessibility audits find issues that automated tools catch and, crucially, issues only humans can detect. Doda Browser includes a built-in accessibility panel that audits any page against WCAG 2.2 AA standards and highlights violations in the DOM tree.
Real-world use: Durga Antivirus Pro runs automated axe audits in CI/CD on every pull request. If accessibility violations are introduced (missing labels, insufficient contrast, missing ARIA attributes), the build fails. This catches over 60% of accessibility regressions before they reach production.
flowchart LR A[Accessibility Audit] --> B[Automated] A --> C[Manual] A --> D[Assistive Tech] B --> E[Lighthouse] B --> F[axe] B --> G[WAVE API] C --> H[Keyboard Only] C --> I[Zoom 400%] C --> J[Reduced Motion] D --> K[Screen Readers] D --> L[Voice Control] style A fill:#4af,color:#fff
Automated Audits
Lighthouse
Built into Chrome DevTools and Doda Browser:
// CLI audit with Lighthouse Node API
const lighthouse = require('lighthouse');
const chromeLauncher = require('chrome-launcher');
const runAudit = async (url) => {
const chrome = await chromeLauncher.launch({ chromeFlags: ['--headless'] });
const options = { logLevel: 'info', output: 'json', onlyCategories: ['accessibility'] };
const runnerResult = await lighthouse(url, options, { port: chrome.port });
await chrome.kill();
const { categories, audits } = runnerResult.lhr;
console.log('Accessibility score:', categories.accessibility.score * 100);
const violations = Object.values(audits)
.filter(audit => audit.score === 0)
.map(audit => ({
title: audit.title,
description: audit.description,
elements: audit.details?.items?.length || 0
}));
return { score: categories.accessibility.score, violations };
};
axe DevTools
More detailed than Lighthouse with specific WCAG mappings:
// axe-core in CI
const axe = require('axe-core');
const { JSDOM } = require('jsdom');
const runAxe = async (html, options = {}) => {
const { window } = new JSDOM(html);
const document = window.document;
const results = await axe.run(document, {
runOnly: ['wcag2a', 'wcag2aa', 'wcag21a', 'wcag21aa'],
...options
});
results.violations.forEach(violation => {
console.log(`[${violation.impact}] ${violation.help}`);
violation.nodes.forEach(node => {
console.log(` - ${node.target.join(', ')}`);
console.log(` - ${node.failureSummary}`);
});
});
return {
violations: results.violations,
passes: results.passes,
incomplete: results.incomplete
};
};
WAVE API
<form>
<!-- Bad — missing label -->
<input type="text" placeholder="Search">
<!-- Bad — empty link -->
<a href="/" class="icon-link"><span class="icon-home"></span></a>
<!-- Bad — low contrast -->
<p style="color: #999; background: #fff;">Light gray on white</p>
</form>
Manual Testing
Automated tools catch ~30% of accessibility issues. The rest require human testing:
Keyboard Navigation
// Test checklist — all interactive elements must be:
Tab, Shift+Tab: Navigate forward and backward
Enter/Space: Activate buttons and links
Arrow keys: Navigate lists, menus, tab panels, sliders
Escape: Close modals, dropdowns, menus
// Ensure visible focus indicators
:focus-visible {
outline: 2px solid #6366f1;
outline-offset: 2px;
}
// Skip link for keyboard users
<a href="#main-content" class="skip-link">Skip to main content</a>
Screen Reader Testing
<!-- NVDA / VoiceOver test scenarios -->
<nav aria-label="Main navigation">
<ul>
<li><a href="/">Home</a></li>
</ul>
</nav>
<!-- Ensure dynamic updates are announced -->
<div aria-live="polite" aria-atomic="true">
Scan complete: 3 threats detected
</div>
<!-- Heading hierarchy test -->
<h1>Page Title</h1>
<h2>Section</h2>
<h3>Subsection</h3>
<h3>Another Subsection</h3>
<h2>Related Content</h2>
Visual Testing
/* Zoom to 400% — no content should be cut off */
html { font-size: 16px; }
@media (min-width: 400%) { /* ... */ }
/* Reduced motion */
@media (prefers-reduced-motion: reduce) {
*, *::before, *::after {
animation-duration: 0.01ms !important;
transition-duration: 0.01ms !important;
}
}
/* High contrast mode */
@media (prefers-contrast: high) {
:root {
--text: #000;
--bg: #fff;
--link: #00f;
}
}
Prioritization Matrix
| Severity | Definition | Examples | Action |
|---|---|---|---|
| Critical | Blocks core functionality | No keyboard access, missing form labels | Fix within 24 hours |
| High | Severely impacts usability | Low contrast, missing headings | Fix within sprint |
| Medium | Makes content harder to access | Redundant alt text, decorative images with alt | Fix within 2 sprints |
| Low | Best practice improvement | Non-semantic elements, missing ARIA landmarks | Add to backlog |
Common Errors
- Relying only on automated tools — Automated audits catch only ~30% of issues. Manual testing with keyboard and screen reader is essential for the remaining 70%.
- Missing form labels — Every
<input>,<select>, and<textarea>needs an associated<label>. Placeholder is not a substitute — it disappears on input. - Insufficient color contrast — WCAG AA requires 4.5:1 for normal text, 3:1 for large text. Tools like Contrast Checker verify compliance.
- Keyboard traps — Users must be able to navigate into and out of every interactive element with keyboard alone. Focus must not get stuck.
- Non-descriptive link text — "Click here" and "Read more" are meaningless for screen reader users who navigate by links list. Use descriptive text.
Practice Questions
- What percentage of accessibility issues do automated tools detect? Approximately 30%. The remaining 70% require manual testing — keyboard navigation, screen reader, zoom testing, and contrast verification.
- What is the difference between WCAG A, AA, and AAA? A is minimum compliance (must-have). AA is the legal standard (should-have). AAA is the highest level (nice-to-have). Most organizations target WCAG 2.2 AA.
- How do you test keyboard accessibility? Tab through all interactive elements. Ensure visible focus indicators. Verify all functionality works with keyboard alone (Enter, Space, Arrow keys, Escape).
- What does
aria-live="polite"do? Tells screen readers to announce content changes in this region when the user is idle, without interrupting current speech. - Why is color contrast ratio important? One in 12 men has some form of color blindness. Low contrast text is unreadable for them and for users with low vision or in bright sunlight.
Challenge
Audit a three-page website using Lighthouse (score), axe (violation details), and WAVE (pass/fail). Manually test keyboard navigation and screen reader flow. Create a prioritized remediation plan with estimated effort for each issue. Fix all critical and high issues. Re-audit to verify improvement.
Real-World Task
Set up the accessibility CI/CD pipeline for the DodaTech tutorials site. Configure axe-core to run in GitHub Actions on every pull request. Add a Lighthouse CI step that blocks merges if the accessibility score drops below 90. Create an accessibility report template that lists violations, affected elements, WCAG criteria, and recommended fixes. Train the team on manual testing with NVDA and keyboard-only navigation.
Previous: SEO Fundamentals | Next: Web Deployment & CI/CD | Related: HTML Fundamentals
Built by the developers of Doda Browser, DodaZIP, and Durga Antivirus Pro.
Built by the developers of DodaTech
Doda Browser, DodaZIP & Durga Antivirus Pro