intermediate general 18 min read
Web Accessibility: Building Inclusive Websites
Learn to create accessible websites that work for everyone.
web accessibility a11y wcag accessible websites
Why Accessibility Matters
Web accessibility ensures that people with disabilities can use your website. It's not just good ethics—it's often legally required and benefits all users.
WCAG Principles (POUR)
Perceivable
Content must be presentable in ways users can perceive.
- Provide text alternatives for images
- Offer captions for videos
- Ensure sufficient color contrast
- Make content adaptable
Operable
Interface must be operable by all users.
- All functionality keyboard accessible
- Give users enough time
- Don't cause seizures
- Provide navigation aids
Understandable
Content must be understandable.
- Make text readable
- Make behavior predictable
- Help users avoid mistakes
Robust
Content must be compatible with current and future tools.
- Use valid HTML
- Maximize compatibility
- Use ARIA appropriately
Practical Implementation
Images
<!-- Informative image -->
<img src="chart.png" alt="Sales increased 50% from Q1 to Q2">
<!-- Decorative image -->
<img src="decoration.png" alt="" role="presentation">
<!-- Complex image -->
<figure>
<img src="complex-chart.png" alt="Annual revenue chart">
<figcaption>
Annual revenue showing growth from $1M in 2020 to $5M in 2025.
</figcaption>
</figure>
Color Contrast
Minimum contrast ratios (WCAG AA):
- Regular text: 4.5:1
- Large text (18pt+): 3:1
- UI components: 3:1
Use our Contrast Checker to verify.
Keyboard Navigation
<!-- Ensure focusable elements -->
<button>Clickable</button>
<a href="/page">Link</a>
<input type="text">
<!-- Custom focusable element -->
<div tabindex="0" role="button" onclick="handleClick()">Custom button</div>
<!-- Skip link -->
<a href="#main-content" class="skip-link">Skip to main content</a>
Focus Styles
/* Don't remove focus styles */
:focus {
outline: 2px solid #3b82f6;
outline-offset: 2px;
}
/* Hide visually but show on focus */
.skip-link {
position: absolute;
left: -9999px;
}
.skip-link:focus {
left: 0;
}
ARIA Attributes
<!-- Roles -->
<nav role="navigation">
<main role="main">
<button role="button">
<!-- States -->
<button aria-pressed="true">Toggle</button>
<div aria-expanded="false">Collapsible</div>
<input aria-invalid="true">
<!-- Properties -->
<input aria-label="Search">
<div aria-labelledby="heading-id">
<input aria-describedby="hint-id">
Forms
<form>
<div>
<label for="email">Email (required)</label>
<input
type="email"
id="email"
name="email"
required
aria-describedby="email-hint email-error"
>
<small id="email-hint">We'll never share your email.</small>
<span id="email-error" role="alert" aria-live="polite"></span>
</div>
</form>
Live Regions
<!-- Polite announcement -->
<div aria-live="polite">Status updates appear here</div>
<!-- Assertive announcement -->
<div aria-live="assertive" role="alert">Error messages here</div>
Testing Accessibility
- Keyboard Testing: Tab through your entire site
- Screen Reader: Test with VoiceOver, NVDA, or JAWS
- Automated Tools: Lighthouse, axe DevTools, WAVE
- Color Blindness: Use browser extensions to simulate
- Zoom Testing: Test at 200% zoom
Checklist
- All images have alt text
- Color contrast meets WCAG AA
- All interactive elements are keyboard accessible
- Focus states are visible
- Forms have labels and error messages
- Page has a logical heading structure
- Skip links are available
- Videos have captions
- Content is readable at 200% zoom