Introduction
Web accessibility ensures people with disabilities can use websites effectively. Beyond compliance, accessible design improves usability for everyone. This guide covers building inclusive web experiences.
Why Accessibility Matters
Statistics
- 15% of world population has some disability
- 1 billion people affected
- Growing as population ages
Benefits
- Legal compliance
- SEO improvement
- Broader audience
- Better usability
- Ethical responsibility
WCAG Guidelines
Four Principles (POUR)
- Perceivable: Can be perceived by users
- Operable: Interface components work
- Understandable: Information is understandable
- Robust: Content works with current and future tools
Levels
| Level | Description |
|---|---|
| A | Basic accessibility |
| AA | Addresses most common barriers |
| AAA | Highest level, not always achievable |
Semantic HTML
Use Proper Elements
<!-- Bad -->
<div onclick="submit()">Submit</div>
<!-- Good -->
<button type="submit">Submit</button>
Headings
<h1>Main Title</h1>
<h2>Section</h2>
<h3>Subsection</h3>
<!-- Skip levels: h1 -> h3 is bad -->
Links and Buttons
<!-- Link: Navigate somewhere -->
<a href="/about">About Us</a>
<!-- Button: Perform action -->
<button>Save</button>
<button>Open menu</button>
Keyboard Navigation
Focus Indicators
/* Always visible focus */
:focus {
outline: 3px solid #2563EB;
outline-offset: 2px;
}
/* Only show when using keyboard */
:focus:not(:focus-visible) {
outline: none;
}
Tab Order
<!-- Logical tab order -->
<form>
<label for="name">Name</label>
<input id="name" type="text" tabindex="1">
<label for="email">Email</label>
<input id="email" type="email" tabindex="2">
</form>
Skip Links
<a href="#main" class="skip-link">Skip to main content</a>
<style>
.skip-link {
position: absolute;
left: -999px;
}
.skip-link:focus {
left: 0;
}
</style>
ARIA
When to Use ARIA
- Enhancing native HTML
- Custom widgets
- Live regions
ARIA Rules
- Use native HTML when possible
- Never change native semantics
- All interactive ARIA needs keyboard support
ARIA Attributes
<!-- Landmark roles -->
<header role="banner">
<main role="main">
<nav role="navigation">
<footer role="contentinfo">
<!-- Interactive widget -->
<button aria-label="Close menu" aria-expanded="false">
<div role="slider" aria-valuemin="0" aria-valuemax="100" aria-valuenow="50">
Live Regions
<!-- Announce updates -->
<div aria-live="polite">Changes saved</div>
<div aria-live="assertive">Error: Invalid input</div>
Images and Media
Alt Text
<!-- Descriptive -->
<img src="cat.jpg" alt="Orange tabby cat sitting on windowsill">
<!-- Empty for decorative -->
<img src="decoration.png" alt="">
<!-- Complex image -->
<img src="chart.png" alt="Bar chart showing sales growth">
Captions and Transcripts
- Video: Captions
- Audio: Transcripts
- Charts: Text alternatives
Forms
Labels
<!-- Explicit label -->
<label for="email">Email</label>
<input id="email" type="email">
<!-- Implicit label -->
<label>
Email
<input type="email">
</label>
Error Handling
<input
id="phone"
type="tel"
aria-invalid="true"
aria-describedby="phone-error"
>
<span id="phone-error" role="alert">
Please enter a valid phone number
</span>
Required Fields
<label for="name">
Name (required)
<input id="name" required aria-required="true">
</label>
Color and Contrast
WCAG Contrast Ratios
- Normal text: 4.5:1 (AA)
- Large text: 3:1 (AA)
- UI components: 3:1 (AA)
Tools
- WebAIM Contrast Checker
- Chrome DevTools color picker
- Browser extensions
Don’t Rely on Color
<!-- Bad: Color only -->
<span class="error">Invalid</span>
<!-- Good: Icon + color + text -->
<span class="error">
<svg aria-hidden="true">...</svg>
Invalid input
</span>
Testing
Automated Testing
- axe DevTools
- WAVE
- Lighthouse
Manual Testing
- Keyboard navigation
- Screen reader testing
- Zoom to 200%
- Disable CSS/images
Screen Readers
- NVDA (Windows)
- VoiceOver (Mac)
- JAWS (Windows)
- TalkBack (Android)
Browser Tools
- Accessibility Inspector (Firefox)
- Accessibility pane (Chrome)
Responsive Design
Text Scaling
/* Use relative units */
body {
font-size: 100%; /* or 1rem */
line-height: 1.5;
}
Touch Targets
/* Minimum 44x44 pixels */
button, a {
min-height: 44px;
min-width: 44px;
}
Conclusion
Accessibility is essential, not optional. Start with semantic HTML, ensure keyboard navigation, use ARIA correctly, and test with real tools. Accessible websites work better for everyone.
Comments