Accessibility (a11y)
ARIA, screen readers, and inclusive design
What is Web Accessibility?
Web accessibility (a11yβ"a" + 11 letters + "y") ensures people with disabilities can use your website. This includes:
ποΈ Visual
Blind, low vision, color blindness
π Auditory
Deaf or hard of hearing
π±οΈ Motor
Limited mobility, keyboard-only users
π§ Cognitive
Learning disabilities, memory issues
π‘ Accessibility benefits everyoneβmobile users, elderly, people with temporary injuries, users in bright sunlight, etc.
Semantic HTML: The Foundation
Using the right HTML elements provides built-in accessibility:
β Inaccessible
<div onclick="submit()">
Click me
</div>
β’ Not keyboard accessible (no Tab focus)
β’ Screen readers don't know it's clickable
β’ No Enter key support
β Accessible
<button onclick="submit()">
Click me
</button>
β Keyboard accessible (Tab + Enter)
β Screen readers announce "Button: Click me"
β Works with assistive tech
Alt Text for Images
Essential for screen reader users and when images fail to load.
β Bad
<img src="dog.jpg" />
<img src="chart.png" alt="image" />
<img src="logo.svg" alt="logo.svg" />
Screen reader says nothing or unhelpful info
β Good
<img src="dog.jpg" alt="Golden retriever playing fetch" />
<img src="chart.png" alt="Sales increased 45% in Q4 2024" />
<!-- Decorative images -->
<img src="divider.png" alt="" />
Descriptive, contextual, or empty for decorative
Keyboard Navigation
Many users navigate without a mouse. Ensure all interactive elements are keyboard accessible.
Key Keyboard Controls
β Not keyboard accessible
<div onclick="showMenu()">
Menu
</div>
<span onclick="openModal()">
View details
</span>
β Keyboard accessible
<button onclick="showMenu()">
Menu
</button>
<button onclick="openModal()">
View details
</button>
ARIA (Accessible Rich Internet Applications)
ARIA attributes enhance accessibility when semantic HTML isn't enough.
β οΈ First Rule of ARIA: Don't use ARIA unless you have to!
Semantic HTML is usually better. Use ARIA only when HTML alone can't convey meaning.
aria-label
Provides accessible name when visible text isn't enough:
<button aria-label="Close dialog">
Γ
</button>
<button aria-label="Search">
π
</button>
<a href="/profile" aria-label="View your profile">
<img src="avatar.jpg" alt="" />
</a>
aria-labelledby & aria-describedby
Link elements to their labels/descriptions:
<h2 id="dialog-title">Confirm deletion</h2>
<p id="dialog-desc">This action cannot be undone.</p>
<div
role="dialog"
aria-labelledby="dialog-title"
aria-describedby="dialog-desc"
>
<!-- dialog content -->
</div>
aria-hidden
Hide decorative elements from screen readers:
<button>
<span aria-hidden="true">β
</span>
Favorite
</button>
<!-- Decorative icons -->
<span class="icon" aria-hidden="true">β</span>
role
Define element purpose when semantic HTML isn't available:
<div role="button" tabindex="0">
Custom button
</div>
<div role="navigation">
<!-- navigation links -->
</div>
<div role="alert">
Form submitted successfully!
</div>
aria-live
Announce dynamic content changes:
<!-- Polite: wait for screen reader to finish -->
<div aria-live="polite">
3 items in cart
</div>
<!-- Assertive: interrupt immediately -->
<div aria-live="assertive" role="alert">
Error: Payment failed!
</div>
Focus Management
Make focus states visible and manage focus flow:
β Bad
/* Removes focus outline */
button:focus {
outline: none;
}
Keyboard users can't see where they are
β Good
/* Custom focus styles */
button:focus {
outline: 2px solid blue;
outline-offset: 2px;
}
/* Or use :focus-visible */
button:focus-visible {
outline: 2px solid blue;
}
Clear visual indicator for keyboard users
β οΈ Common Accessibility Mistakes
- β Using divs/spans for buttons: Use
<button>instead - β Missing alt text: Every image needs
alt(even if empty for decorative) - β Poor color contrast: Text must be readable (4.5:1 ratio minimum)
- β No keyboard access: All interactive elements must be keyboard accessible
- β Removing focus outlines: Don't use
outline: nonewithout custom focus styles - β Auto-playing media: Don't auto-play videos/audio without controls
- β Form inputs without labels: Every input needs a
<label>
β Accessibility Checklist
- β Use semantic HTML:
<button>,<nav>,<main>, etc. - β Provide alt text: Descriptive for meaningful images, empty for decorative
- β Ensure keyboard navigation: Test with Tab key only
- β Maintain color contrast: Use online contrast checkers
- β Label all form inputs: Use
<label for="id"> - β Use ARIA sparingly: Only when semantic HTML isn't enough
- β Provide skip links: "Skip to main content" for keyboard users
- β Test with screen readers: NVDA (Windows), VoiceOver (Mac), JAWS
- β Use heading hierarchy: h1 β h2 β h3 (don't skip levels)
π οΈ Testing Tools
- Lighthouse: Built into Chrome DevTools, audits accessibility
- WAVE: Browser extension for visual accessibility evaluation
- axe DevTools: Comprehensive accessibility testing
- Keyboard testing: Navigate your site using only Tab, Enter, Space, Arrow keys
- Screen readers: NVDA (free, Windows), VoiceOver (Mac), JAWS (Windows)
- Color contrast checker: WebAIM Contrast Checker