Error occurred
×
```
**First rule of ARIA:** Don't use ARIA if semantic HTML works
### 3. Keyboard Navigation
**All interactive elements must be keyboard accessible:**
```javascript
// Add keyboard support to custom elements
{
if (e.key === 'Enter' || e.key === ' ') {
handleClick();
}
}}
>
Click me
```
**Tab order:**
- Use `tabindex="0"` for custom interactive elements
- Avoid `tabindex > 0` (creates confusing tab order)
- Use `tabindex="-1"` for programmatic focus only
**Focus management:**
- Visible focus indicators
- Trap focus in modals
- Return focus when closing dialogs
- Skip links for main content
### 4. Alt Text and Images
**Informative images:**
```html
```
**Decorative images:**
```html
```
**Complex images:**
```html
Detailed description of the chart data...
```
### 5. Color and Contrast
**Contrast ratios (WCAG AA):**
- Normal text: 4.5:1 minimum
- Large text (18pt+): 3:1 minimum
- UI components: 3:1 minimum
**Don't rely on color alone:**
```html
Error
Error:
Invalid input
```
### 6. Forms and Labels
**Every input needs a label:**
```html
Email
Email
```
**Error messages:**
```html
Password must be at least 8 characters
```
### 7. Headings and Document Structure
**Proper heading hierarchy:**
```html
Page Title
Section 1
Subsection 1.1
Subsection 1.2
Section 2
```
**Don't skip levels:** h1 → h2 → h3 (not h1 → h3)
### 8. Dynamic Content
**Announce updates to screen readers:**
```html
5 new messages
Your session will expire in 1 minute
```
**Loading states:**
```html
Loading
```
### 9. Screen Reader Testing
**Screen reader only text:**
```css
.sr-only {
position: absolute;
width: 1px;
height: 1px;
padding: 0;
margin: -1px;
overflow: hidden;
clip: rect(0, 0, 0, 0);
white-space: nowrap;
border-width: 0;
}
```
**Hide decorative elements:**
```html
```
### 10. Common Issues to Check
**Missing:**
- [ ] Alt text on images
- [ ] Labels on form inputs
- [ ] Proper heading hierarchy
- [ ] Keyboard focus indicators
- [ ] ARIA labels on icon buttons
**Improper:**
- [ ] Low contrast text
- [ ] Non-semantic markup (divs as buttons)
- [ ] Missing focus management in modals
- [ ] Keyboard traps
- [ ] Auto-playing media
**Testing:**
- [ ] Keyboard only navigation
- [ ] Screen reader (NVDA, JAWS, VoiceOver)
- [ ] Color blindness simulation
- [ ] Zoom to 200%
- [ ] Automated tools (axe, Lighthouse)
### 11. Automated Testing
**Tools:**
```bash
# Lighthouse
npx lighthouse https://example.com --only-categories=accessibility
# axe-core
npm install --save-dev @axe-core/cli
npx axe https://example.com
# pa11y
npm install --save-dev pa11y
npx pa11y https://example.com
```
**In tests:**
```javascript
import { axe } from 'jest-axe';
test('should have no accessibility violations', async () => {
const { container } = render(
);
const results = await axe(container);
expect(results).toHaveNoViolations();
});
```
### 12. WCAG 2.1 Level AA Checklist
**Perceivable:**
- [ ] Text alternatives for non-text content
- [ ] Captions for audio/video
- [ ] Content adaptable (semantic markup)
- [ ] Sufficient color contrast
**Operable:**
- [ ] Keyboard accessible
- [ ] No keyboard traps
- [ ] Adequate time limits (adjustable)
- [ ] No seizure-inducing flashing
- [ ] Skip navigation links
- [ ] Descriptive page titles
- [ ] Focus order makes sense
- [ ] Link purpose clear from context
**Understandable:**
- [ ] Language of page specified (``)
- [ ] Predictable navigation
- [ ] Input assistance (labels, instructions, error messages)
**Robust:**
- [ ] Valid HTML
- [ ] Name, role, value for custom widgets
- [ ] Compatible with assistive technologies
## Best Practices
- Build accessibility in from start
- Test with real assistive technologies
- Use semantic HTML first, ARIA second
- Maintain logical document structure
- Provide multiple ways to access content
- Test keyboard navigation thoroughly
- Don't disable zoom
- Use landmarks and headings
## Supporting Files
- `reference/wcag-checklist.md`: Full WCAG 2.1 AA checklist
- `reference/aria-patterns.md`: Common ARIA widget patterns