Back to Blog
AccessibilityTestingWCAGWeb Development

Accessibility Testing: Building Inclusive Web Applications

Test and fix accessibility issues. From automated tools to manual testing to WCAG compliance strategies.

B
Bootspring Team
Engineering
July 28, 2024
5 min read

Accessibility ensures everyone can use your application, including people with disabilities. It's also a legal requirement in many jurisdictions. Here's how to test and improve accessibility.

Core Principles (WCAG)#

POUR Principles: Perceivable - Text alternatives for images - Captions for video - Sufficient color contrast Operable - Keyboard accessible - Enough time to read - No seizure-inducing content Understandable - Readable text - Predictable navigation - Input assistance Robust - Compatible with assistive tech - Valid HTML - Future-proof

Automated Testing#

Axe DevTools#

1// axe-core in tests 2import { axe, toHaveNoViolations } from 'jest-axe'; 3 4expect.extend(toHaveNoViolations); 5 6describe('Button', () => { 7 it('has no accessibility violations', async () => { 8 const { container } = render(<Button>Click me</Button>); 9 const results = await axe(container); 10 expect(results).toHaveNoViolations(); 11 }); 12});

Lighthouse CI#

1# GitHub Actions 2- name: Lighthouse CI 3 uses: treosh/lighthouse-ci-action@v10 4 with: 5 urls: | 6 https://example.com/ 7 https://example.com/products 8 budgetPath: ./lighthouse-budget.json 9 uploadArtifacts: true 10 11# lighthouse-budget.json 12{ 13 "assertions": { 14 "categories:accessibility": ["error", { "minScore": 0.9 }] 15 } 16}

ESLint Plugin#

1// .eslintrc.js 2module.exports = { 3 plugins: ['jsx-a11y'], 4 extends: ['plugin:jsx-a11y/recommended'], 5 rules: { 6 'jsx-a11y/alt-text': 'error', 7 'jsx-a11y/anchor-has-content': 'error', 8 'jsx-a11y/click-events-have-key-events': 'error', 9 'jsx-a11y/no-static-element-interactions': 'error', 10 }, 11};

Manual Testing#

Keyboard Navigation#

Test all functionality with keyboard only: Tab Move to next focusable element Shift+Tab Move to previous element Enter/Space Activate buttons, links Arrow keys Navigate menus, sliders Escape Close modals, cancel Check for: - Visible focus indicators - Logical tab order - No keyboard traps - Skip links for navigation

Screen Reader Testing#

Popular screen readers: - VoiceOver (Mac): Cmd+F5 to enable - NVDA (Windows): Free download - JAWS (Windows): Commercial Test scenarios: - Navigate by headings (H key) - Navigate by landmarks (D key) - Read page content - Fill out forms - Interact with custom components

Common Issues and Fixes#

Images#

1<!-- ❌ Missing alt text --> 2<img src="product.jpg"> 3 4<!-- ✅ Descriptive alt text --> 5<img src="product.jpg" alt="Red wireless headphones with noise cancellation"> 6 7<!-- ✅ Decorative image (empty alt) --> 8<img src="decorative-line.svg" alt=""> 9 10<!-- ✅ Complex images --> 11<figure> 12 <img src="chart.png" alt="Sales increased 50% in Q4"> 13 <figcaption>Quarterly sales chart showing growth trajectory</figcaption> 14</figure>

Forms#

1<!-- ❌ No label association --> 2<input type="email" placeholder="Email"> 3 4<!-- ✅ Proper label --> 5<label for="email">Email address</label> 6<input type="email" id="email" required aria-describedby="email-hint"> 7<span id="email-hint">We'll never share your email</span> 8 9<!-- ✅ Error messages --> 10<input type="email" id="email" aria-invalid="true" aria-describedby="email-error"> 11<span id="email-error" role="alert">Please enter a valid email address</span>
1<!-- ❌ Non-descriptive --> 2<a href="/products">Click here</a> 3<button>Submit</button> 4 5<!-- ✅ Descriptive --> 6<a href="/products">View all products</a> 7<button>Submit order</button> 8 9<!-- ✅ Icon buttons with labels --> 10<button aria-label="Close dialog"> 11 <svg aria-hidden="true">...</svg> 12</button>

Color Contrast#

1/* WCAG AA requirements: 2 Normal text: 4.5:1 contrast ratio 3 Large text (18px+): 3:1 contrast ratio 4*/ 5 6/* ❌ Poor contrast */ 7.text { 8 color: #999; 9 background: #fff; 10} 11 12/* ✅ Good contrast */ 13.text { 14 color: #595959; /* 7:1 ratio */ 15 background: #fff; 16} 17 18/* Check with tools: 19 - WebAIM Contrast Checker 20 - Chrome DevTools color picker 21*/

Focus Indicators#

1/* ❌ Removing focus outline */ 2*:focus { 3 outline: none; 4} 5 6/* ✅ Custom but visible focus */ 7:focus-visible { 8 outline: 2px solid #4f46e5; 9 outline-offset: 2px; 10} 11 12/* ✅ Button focus */ 13.button:focus-visible { 14 outline: 2px solid currentColor; 15 outline-offset: 2px; 16 box-shadow: 0 0 0 4px rgba(79, 70, 229, 0.2); 17}

ARIA Usage#

1<!-- Use native HTML when possible --> 2<!-- ❌ Over-engineering --> 3<div role="button" tabindex="0" onclick="submit()">Submit</div> 4 5<!-- ✅ Native element --> 6<button type="submit">Submit</button> 7 8<!-- ARIA for custom components --> 9<div 10 role="tablist" 11 aria-label="Product information tabs" 12> 13 <button role="tab" aria-selected="true" aria-controls="panel-1">Description</button> 14 <button role="tab" aria-selected="false" aria-controls="panel-2">Reviews</button> 15</div> 16 17<div role="tabpanel" id="panel-1" aria-labelledby="tab-1"> 18 Content... 19</div>

Live Regions#

1<!-- Announce dynamic updates --> 2<div aria-live="polite" aria-atomic="true"> 3 <!-- Screen reader announces when content changes --> 4 Item added to cart 5</div> 6 7<!-- Urgent announcements --> 8<div role="alert" aria-live="assertive"> 9 Error: Please fix the highlighted fields 10</div>

Testing Checklist#

1## Automated Tests 2- [ ] axe-core passes 3- [ ] Lighthouse accessibility > 90% 4- [ ] ESLint jsx-a11y passes 5 6## Keyboard 7- [ ] All interactive elements focusable 8- [ ] Focus order logical 9- [ ] Focus indicators visible 10- [ ] No keyboard traps 11- [ ] Skip link present 12 13## Screen Reader 14- [ ] Heading hierarchy correct 15- [ ] Landmarks used properly 16- [ ] Images have alt text 17- [ ] Forms labeled correctly 18- [ ] Dynamic content announced 19 20## Visual 21- [ ] Color contrast sufficient 22- [ ] Not relying on color alone 23- [ ] Text resizable to 200% 24- [ ] Works at 400% zoom

Conclusion#

Accessibility is an ongoing practice, not a checkbox. Start with automated testing, complement with manual testing, and involve users with disabilities when possible.

Building accessible applications benefits everyone—and it's the right thing to do.

Share this article

Help spread the word about Bootspring