Web Accessibility Skill
Purpose
Comprehensive WCAG 2.1 AA accessibility rules for web development. Covers semantic HTML, ARIA patterns, keyboard navigation, focus management, color contrast, and screen reader testing for React/Next.js applications.
Aspect Files
| File |
Coverage |
references/web-semantic-html.md |
Semantic elements, text alternatives, landmark roles, skip links, heading hierarchy |
references/web-aria.md |
ARIA labels, roles, live regions, dialog/tab/progressbar patterns, state attributes |
references/web-keyboard-focus.md |
:focus-visible, focus trapping, tabIndex, keyboard event handlers, focus order |
references/web-forms.md |
Label association, error announcements, required indicators, fieldset/legend, autocomplete |
references/web-contrast.md |
Contrast ratios, forced-colors, prefers-color-scheme, visually-hidden, motion reduction |
references/web-wcag-reference.md |
WCAG 2.1 success criteria (A/AA), ARIA patterns quick reference, screen reader commands, checklist |
Fix Templates
| Template |
When to Apply |
add_alt_text |
<img> missing alt attribute or has alt="" on informative image |
make_decorative |
Decorative image with meaningful alt text — set alt="" and role="presentation" |
add_aria_label |
Interactive element has no accessible name (icon button, custom widget) |
add_heading_level |
Heading hierarchy skips levels (h1 → h3), or visual heading uses <div> |
add_focus_visible |
:focus outline removed via CSS without :focus-visible replacement |
add_form_label |
<input> has no associated <label>, aria-label, or aria-labelledby |
other_manual |
Complex widget, custom component, or context-dependent fix requiring manual review |
Quick Reference
Semantic HTML
<!-- Prefer native elements -->
<button <!-- ✅ -->
<div role="button" <!-- ❌ avoid -->
<!-- Landmark structure -->
<header>...</header>
<nav aria-label="Primary">...</nav>
<main>...</main>
<aside>...</aside>
<footer>...</footer>
ARIA Labels
<!-- When visible label is absent -->
<button aria-label="Close dialog">✕</button>
<!-- Link label from another element -->
<h2 id="article-title">...</h2>
<a aria-labelledby="article-title">Read more</a>
<!-- Live region for dynamic content -->
<div aria-live="polite" aria-atomic="true">Status updated</div>
Keyboard Navigation
/* Never suppress focus without replacement */
:focus-visible {
outline: 2px solid #005fcc;
outline-offset: 2px;
}
// tabIndex rules
tabIndex={0} // Natural keyboard order
tabIndex={-1} // Programmatic focus only, not in tab order
// Never use positive tabIndex values
React Patterns
// Accessible icon button
<button aria-label="Delete item"
<TrashIcon aria-hidden="true" />
</button>
// Conditional ARIA state
<button aria-expanded={isOpen} aria-controls="menu-id">
Menu
</button>
Testing Tools
| Tool |
Purpose |
| Lighthouse |
Automated audit in Chrome DevTools (score 0-100) |
| axe-core / axe DevTools |
Rule-based violation detection, integrates with Jest/Playwright |
| VoiceOver (macOS/iOS) |
Screen reader — Cmd+F5 to toggle, navigate with VO+Arrow |
| NVDA (Windows) |
Free screen reader for Windows cross-browser testing |
| Chrome DevTools |
Accessibility tree inspector, contrast checker in Elements panel |
Agents Using This Skill
epost-a11y-specialist — Multi-platform accessibility orchestrator
Related Documents
ios-a11y — iOS counterpart (VoiceOver, UIKit, SwiftUI)
android-a11y — Android counterpart (TalkBack, Compose, Semantics)
a11y — Platform-agnostic core principles (POUR, scoring)
1---2name: web-a11y3description: (ePost) Use when web accessibility issues arise — ARIA roles, keyboard navigation, focus trapping, alt text, contrast, screen readers4---5
6# Web Accessibility Skill
7
8## Purpose
9
10Comprehensive WCAG 2.1 AA accessibility rules for web development. Covers semantic HTML, ARIA patterns, keyboard navigation, focus management, color contrast, and screen reader testing for React/Next.js applications.
11
12## Aspect Files
13
14| File | Coverage |
15|------|----------|
16| `references/web-semantic-html.md` | Semantic elements, text alternatives, landmark roles, skip links, heading hierarchy |
17| `references/web-aria.md` | ARIA labels, roles, live regions, dialog/tab/progressbar patterns, state attributes |
18| `references/web-keyboard-focus.md` | :focus-visible, focus trapping, tabIndex, keyboard event handlers, focus order |
19| `references/web-forms.md` | Label association, error announcements, required indicators, fieldset/legend, autocomplete |
20| `references/web-contrast.md` | Contrast ratios, forced-colors, prefers-color-scheme, visually-hidden, motion reduction |
21| `references/web-wcag-reference.md` | WCAG 2.1 success criteria (A/AA), ARIA patterns quick reference, screen reader commands, checklist |
22
23## Fix Templates
24
25| Template | When to Apply |
26|----------|--------------|
27| `add_alt_text` | `<img>` missing `alt` attribute or has `alt=""` on informative image |
28| `make_decorative` | Decorative image with meaningful alt text — set `alt=""` and `role="presentation"` |
29| `add_aria_label` | Interactive element has no accessible name (icon button, custom widget) |
30| `add_heading_level` | Heading hierarchy skips levels (h1 → h3), or visual heading uses `<div>` |
31| `add_focus_visible` | `:focus` outline removed via CSS without `:focus-visible` replacement |
32| `add_form_label` | `<input>` has no associated `<label>`, `aria-label`, or `aria-labelledby` |
33| `other_manual` | Complex widget, custom component, or context-dependent fix requiring manual review |
34
35## Quick Reference
36
37### Semantic HTML
38
39```html
40<!-- Prefer native elements -->
41<button onclick="save()">Save</button> <!-- ✅ -->
42<div role="button" onclick="save()">Save</div> <!-- ❌ avoid -->
43
44<!-- Landmark structure -->
45<header>...</header>
46<nav aria-label="Primary">...</nav>
47<main>...</main>
48<aside>...</aside>
49<footer>...</footer>
50```
51
52### ARIA Labels
53
54```html
55<!-- When visible label is absent -->
56<button aria-label="Close dialog">✕</button>
57
58<!-- Link label from another element -->
59<h2 id="article-title">...</h2>
60<a aria-labelledby="article-title">Read more</a>
61
62<!-- Live region for dynamic content -->
63<div aria-live="polite" aria-atomic="true">Status updated</div>
64```
65
66### Keyboard Navigation
67
68```css
69/* Never suppress focus without replacement */
70:focus-visible {
71 outline: 2px solid #005fcc;
72 outline-offset: 2px;
73}
74```
75
76```js
77// tabIndex rules
78tabIndex={0} // Natural keyboard order
79tabIndex={-1} // Programmatic focus only, not in tab order
80// Never use positive tabIndex values
81```
82
83### React Patterns
84
85```jsx
86// Accessible icon button
87<button aria-label="Delete item" onClick={handleDelete}>
88 <TrashIcon aria-hidden="true" />
89</button>
90
91// Conditional ARIA state
92<button aria-expanded={isOpen} aria-controls="menu-id">
93 Menu
94</button>
95```
96
97## Testing Tools
98
99| Tool | Purpose |
100|------|---------|
101| Lighthouse | Automated audit in Chrome DevTools (score 0-100) |
102| axe-core / axe DevTools | Rule-based violation detection, integrates with Jest/Playwright |
103| VoiceOver (macOS/iOS) | Screen reader — `Cmd+F5` to toggle, navigate with `VO+Arrow` |
104| NVDA (Windows) | Free screen reader for Windows cross-browser testing |
105| Chrome DevTools | Accessibility tree inspector, contrast checker in Elements panel |
106
107## Agents Using This Skill
108
109- `epost-a11y-specialist` — Multi-platform accessibility orchestrator
110
111## Related Documents
112
113- `ios-a11y` — iOS counterpart (VoiceOver, UIKit, SwiftUI)
114- `android-a11y` — Android counterpart (TalkBack, Compose, Semantics)
115- `a11y` — Platform-agnostic core principles (POUR, scoring)