Systematically improve accessibility so the interface works for users with disabilities, temporary impairments, and assistive technology.
This skill focuses on remediation and implementation, not just scoring. It complements audit (which measures across dimensions) and harden (which handles edge cases broadly). Use this when accessibility is the primary goal.
MANDATORY PREPARATION
Users start this workflow with /a11y. Once this skill is active, load $frontend-design — it contains design principles, anti-patterns, and the Context Gathering Protocol. Follow that protocol before proceeding — if no design context exists yet, you MUST load $setup first.
Consult the accessibility testing reference for automated tool integration (axe, WAVE, Pa11y) and CI workflow guidance.
Consult the colorblindness UX reference when color is carrying meaning in states, charts, or validation.
Consult the component accessibility reference for keyboard support, focus handling, skip links, and hidden content patterns.
Consult the interaction design reference for focus, loading, transitions, and feedback states.
Consult the semantic color reference when checking whether color communicates state or just decoration.
Consult the responsive design reference when accessibility needs to adapt across small screens, touch contexts, or zoom levels.
Assess Accessibility
Identify what is broken and who it affects:
Run automated checks first:
- Use axe-core, WAVE, or Pa11y against critical pages
- Target WCAG 2.1 AA as the baseline
- Document violations by severity: critical (blocks task), serious (difficult workaround), moderate (annoying), minor (polish)
- Treat automated results as a fast warning system, not a complete audit
Test keyboard navigation manually:
- Unplug the mouse. Can you reach every interactive element?
- Is the tab order logical and predictable?
- Are focus indicators visible and clear?
- Are there keyboard traps (places you cannot tab out of)?
- Do custom components respond to Enter, Space, Escape, and arrow keys?
Test with a screen reader:
- Use NVDA (Windows), VoiceOver (macOS/iOS), or TalkBack (Android)
- Navigate by headings, landmarks, and form fields
- Verify that dynamic content changes are announced
- Check that decorative elements are hidden from assistive technology
- Confirm that error messages and status updates are read aloud
Check visual accessibility:
- Verify contrast ratios: 4.5:1 for normal text, 3:1 for large text, 3:1 for UI components
- Test at 200% and 400% zoom without horizontal scrolling or content loss
- Simulate color-vision deficiencies (deuteranopia, protanopia, tritanopia)
- Ensure color is not the only signal for state or meaning
- Check that text remains readable when high-contrast mode is enabled
Check motion and animation:
- Enable
prefers-reduced-motion and confirm the interface remains usable
- Ensure no critical information is hidden behind motion-only reveals
- Verify that auto-playing content can be paused or stopped
Remediate by Area
Semantic HTML
Use the right element for the job. Native HTML elements come with built-in accessibility.
Fixes:
- Replace
<div> or <span> buttons with <button> elements
- Use
<a> only for navigation, <button> for actions
- Use
<nav>, <main>, <aside>, <header>, <footer> for landmarks
- Use
<ul> / <ol> for lists, not styled divs
- Use
<table> for tabular data, not CSS grid layouts
- Use
<label> explicitly associated with inputs via for attribute
- Use
<fieldset> and <legend> for related form groups
Anti-patterns to remove:
- Clickable divs without
role, tabindex, and keyboard handlers
- Headings used only for sizing (
<h1> through <h6> should reflect document structure)
- Placeholder text used as labels
- Empty links or buttons with only icons and no accessible name
Keyboard Navigation
Every interactive element must be reachable and operable without a mouse.
Fixes:
- Ensure all interactive elements have
tabindex="0" (or are naturally focusable)
- Remove
tabindex="-1" from elements that should be focusable
- Remove positive
tabindex values (they create unpredictable order)
- Implement keyboard handlers for custom components:
- Buttons: Enter and Space activate
- Toggles: Enter or Space toggle
- Menus: Enter opens, Escape closes, arrow keys navigate
- Modals: Tab cycles within, Escape closes, focus returns to trigger
- Accordions: Enter or Space toggle, arrow keys move between items
- Ensure focus is visible: provide a clear focus ring that is not suppressed by
outline: none without replacement
Focus Management
Focus must be intentional, visible, and predictable.
Fixes:
- On route change in SPAs, move focus to the new page heading or main content
- When a modal opens, trap focus inside and return focus to the trigger on close
- When a dropdown opens, move focus to the first item
- When an error occurs, move focus to the error summary or first invalid field
- When content is removed, move focus to a logical remaining element (not document.body)
- Do not auto-focus fields on page load unless the user explicitly initiated the action
ARIA
Use ARIA only when native HTML is insufficient. ARIA does not change behavior, only semantics.
When to use ARIA:
- Custom components that have no native HTML equivalent (tabs, tree views, complex menus)
- Landmark regions that need explicit roles
- Live regions for dynamic content announcements
- Accessible names or descriptions that cannot be provided by visible text
Common ARIA fixes:
- Add
role="dialog" and aria-modal="true" to modals
- Add
aria-expanded to disclosure buttons and accordion triggers
- Add
aria-current="page" to the active navigation item
- Add
aria-live="polite" or aria-live="assertive" to status containers
- Add
aria-label or aria-labelledby to icons and icon-only buttons
- Add
aria-describedby to inputs with helper text or error messages
- Add
aria-invalid="true" to invalid form fields
ARIA anti-patterns:
- Do not add
role="button" to actual <button> elements
- Do not use
aria-hidden="true" on focusable elements
- Do not use conflicting roles (e.g.,
role="button" on a link)
- Do not nest interactive elements inside each other
- Do not rely on ARIA alone without implementing the corresponding keyboard behavior
Color and Contrast
Ensure information is perceivable regardless of visual ability.
Fixes:
- Meet WCAG AA contrast: 4.5:1 for normal text, 3:1 for large text and UI components
- Never rely on color alone for state, error, or required indicators
- Pair semantic colors with text labels, icons, or shape differences
- Check semantic color ramps under color-vision simulation
- Ensure focus indicators have sufficient contrast against their background
- Provide visible text labels or icons alongside colored status indicators
Screen Reader Support
Ensure assistive technology users receive equivalent information.
Fixes:
- Provide descriptive alt text for informative images; use empty alt for decorative images
- Use
aria-live regions for dynamic updates (search results, form submissions, notifications)
- Ensure form errors are associated with their fields via
aria-describedby
- Provide accessible names for all icons, buttons, and controls
- Use headings hierarchically (do not skip levels)
- Mark decorative SVGs with
aria-hidden="true" or role="img" with a title
- Ensure tables have proper
th headers and scope attributes
Motion and Animation
Respect users who cannot tolerate or do not want motion.
Fixes:
- Wrap animations in
@media (prefers-reduced-motion: no-preference) or provide reduced-motion alternatives
- For
prefers-reduced-motion: reduce, replace motion with instant state changes or subtle fades
- Do not auto-play video or animations without a pause/stop control
- Ensure parallax and scroll-triggered effects do not cause disorientation
- Respect motion preferences in carousels, slideshows, and onboarding tours
Verify Improvements
After remediation, verify that fixes work:
- Re-run automated checks: confirm previous violations are resolved and no new ones were introduced
- Keyboard pass: tab through every interactive element again
- Screen reader pass: navigate by headings, landmarks, and form fields
- Zoom test: confirm usability at 200% and 400%
- Color-vision simulation: confirm states and charts remain distinguishable
- Reduced motion: enable
prefers-reduced-motion and confirm the interface is still usable
- Real devices: test on actual assistive technology when possible
Practical Checklist
NEVER:
- Rely on automated testing alone
- Use ARIA without implementing corresponding keyboard behavior
- Rely on color alone for important information
- Remove focus indicators without providing a replacement
- Skip manual testing with real assistive technology for critical flows
- Treat accessibility as a one-time fix rather than an ongoing practice
Remember: accessible design is usable design. Fixing accessibility issues usually improves the experience for everyone.
1---
2name: a11y
3description: Systematically audit and remediate accessibility issues in UI, focusing on keyboard navigation, screen reader support, color contrast, semantic HTML, ARIA usage, and motion sensitivity. Use when the user wants to improve accessibility, make a component accessible, fix WCAG violations, add keyboard support, or ensure screen reader compatibility.
4metadata:
5 argument-hint: "[target]"
6---
7
8Systematically improve accessibility so the interface works for users with disabilities, temporary impairments, and assistive technology.
9
10This skill focuses on remediation and implementation, not just scoring. It complements `audit` (which measures across dimensions) and `harden` (which handles edge cases broadly). Use this when accessibility is the primary goal.
11
12## MANDATORY PREPARATION
13
14Users start this workflow with `/a11y`. Once this skill is active, load $frontend-design — it contains design principles, anti-patterns, and the **Context Gathering Protocol**. Follow that protocol before proceeding — if no design context exists yet, you MUST load $setup first.
15
16Consult the [accessibility testing reference](../frontend-design/reference/accessibility-testing.md) for automated tool integration (axe, WAVE, Pa11y) and CI workflow guidance.
17Consult the [colorblindness UX reference](../frontend-design/reference/colorblindness-ux.md) when color is carrying meaning in states, charts, or validation.
18Consult the [component accessibility reference](../frontend-design/reference/component-accessibility.md) for keyboard support, focus handling, skip links, and hidden content patterns.
19Consult the [interaction design reference](../frontend-design/reference/interaction-design.md) for focus, loading, transitions, and feedback states.
20Consult the [semantic color reference](../frontend-design/reference/semantic-color.md) when checking whether color communicates state or just decoration.
21Consult the [responsive design reference](../frontend-design/reference/responsive-design.md) when accessibility needs to adapt across small screens, touch contexts, or zoom levels.
22
23## Assess Accessibility
24
25Identify what is broken and who it affects:
26
271. **Run automated checks first**:
28 - Use axe-core, WAVE, or Pa11y against critical pages
29 - Target WCAG 2.1 AA as the baseline
30 - Document violations by severity: critical (blocks task), serious (difficult workaround), moderate (annoying), minor (polish)
31 - Treat automated results as a fast warning system, not a complete audit
32
332. **Test keyboard navigation manually**:
34 - Unplug the mouse. Can you reach every interactive element?
35 - Is the tab order logical and predictable?
36 - Are focus indicators visible and clear?
37 - Are there keyboard traps (places you cannot tab out of)?
38 - Do custom components respond to Enter, Space, Escape, and arrow keys?
39
403. **Test with a screen reader**:
41 - Use NVDA (Windows), VoiceOver (macOS/iOS), or TalkBack (Android)
42 - Navigate by headings, landmarks, and form fields
43 - Verify that dynamic content changes are announced
44 - Check that decorative elements are hidden from assistive technology
45 - Confirm that error messages and status updates are read aloud
46
474. **Check visual accessibility**:
48 - Verify contrast ratios: 4.5:1 for normal text, 3:1 for large text, 3:1 for UI components
49 - Test at 200% and 400% zoom without horizontal scrolling or content loss
50 - Simulate color-vision deficiencies (deuteranopia, protanopia, tritanopia)
51 - Ensure color is not the only signal for state or meaning
52 - Check that text remains readable when high-contrast mode is enabled
53
545. **Check motion and animation**:
55 - Enable `prefers-reduced-motion` and confirm the interface remains usable
56 - Ensure no critical information is hidden behind motion-only reveals
57 - Verify that auto-playing content can be paused or stopped
58
59## Remediate by Area
60
61### Semantic HTML
62
63Use the right element for the job. Native HTML elements come with built-in accessibility.
64
65**Fixes**:
66- Replace `<div>` or `<span>` buttons with `<button>` elements
67- Use `<a>` only for navigation, `<button>` for actions
68- Use `<nav>`, `<main>`, `<aside>`, `<header>`, `<footer>` for landmarks
69- Use `<ul>` / `<ol>` for lists, not styled divs
70- Use `<table>` for tabular data, not CSS grid layouts
71- Use `<label>` explicitly associated with inputs via `for` attribute
72- Use `<fieldset>` and `<legend>` for related form groups
73
74**Anti-patterns to remove**:
75- Clickable divs without `role`, `tabindex`, and keyboard handlers
76- Headings used only for sizing (`<h1>` through `<h6>` should reflect document structure)
77- Placeholder text used as labels
78- Empty links or buttons with only icons and no accessible name
79
80### Keyboard Navigation
81
82Every interactive element must be reachable and operable without a mouse.
83
84**Fixes**:
85- Ensure all interactive elements have `tabindex="0"` (or are naturally focusable)
86- Remove `tabindex="-1"` from elements that should be focusable
87- Remove positive `tabindex` values (they create unpredictable order)
88- Implement keyboard handlers for custom components:
89 - Buttons: Enter and Space activate
90 - Toggles: Enter or Space toggle
91 - Menus: Enter opens, Escape closes, arrow keys navigate
92 - Modals: Tab cycles within, Escape closes, focus returns to trigger
93 - Accordions: Enter or Space toggle, arrow keys move between items
94- Ensure focus is visible: provide a clear focus ring that is not suppressed by `outline: none` without replacement
95
96### Focus Management
97
98Focus must be intentional, visible, and predictable.
99
100**Fixes**:
101- On route change in SPAs, move focus to the new page heading or main content
102- When a modal opens, trap focus inside and return focus to the trigger on close
103- When a dropdown opens, move focus to the first item
104- When an error occurs, move focus to the error summary or first invalid field
105- When content is removed, move focus to a logical remaining element (not document.body)
106- Do not auto-focus fields on page load unless the user explicitly initiated the action
107
108### ARIA
109
110Use ARIA only when native HTML is insufficient. ARIA does not change behavior, only semantics.
111
112**When to use ARIA**:
113- Custom components that have no native HTML equivalent (tabs, tree views, complex menus)
114- Landmark regions that need explicit roles
115- Live regions for dynamic content announcements
116- Accessible names or descriptions that cannot be provided by visible text
117
118**Common ARIA fixes**:
119- Add `role="dialog"` and `aria-modal="true"` to modals
120- Add `aria-expanded` to disclosure buttons and accordion triggers
121- Add `aria-current="page"` to the active navigation item
122- Add `aria-live="polite"` or `aria-live="assertive"` to status containers
123- Add `aria-label` or `aria-labelledby` to icons and icon-only buttons
124- Add `aria-describedby` to inputs with helper text or error messages
125- Add `aria-invalid="true"` to invalid form fields
126
127**ARIA anti-patterns**:
128- Do not add `role="button"` to actual `<button>` elements
129- Do not use `aria-hidden="true"` on focusable elements
130- Do not use conflicting roles (e.g., `role="button"` on a link)
131- Do not nest interactive elements inside each other
132- Do not rely on ARIA alone without implementing the corresponding keyboard behavior
133
134### Color and Contrast
135
136Ensure information is perceivable regardless of visual ability.
137
138**Fixes**:
139- Meet WCAG AA contrast: 4.5:1 for normal text, 3:1 for large text and UI components
140- Never rely on color alone for state, error, or required indicators
141- Pair semantic colors with text labels, icons, or shape differences
142- Check semantic color ramps under color-vision simulation
143- Ensure focus indicators have sufficient contrast against their background
144- Provide visible text labels or icons alongside colored status indicators
145
146### Screen Reader Support
147
148Ensure assistive technology users receive equivalent information.
149
150**Fixes**:
151- Provide descriptive alt text for informative images; use empty alt for decorative images
152- Use `aria-live` regions for dynamic updates (search results, form submissions, notifications)
153- Ensure form errors are associated with their fields via `aria-describedby`
154- Provide accessible names for all icons, buttons, and controls
155- Use headings hierarchically (do not skip levels)
156- Mark decorative SVGs with `aria-hidden="true"` or `role="img"` with a title
157- Ensure tables have proper `th` headers and `scope` attributes
158
159### Motion and Animation
160
161Respect users who cannot tolerate or do not want motion.
162
163**Fixes**:
164- Wrap animations in `@media (prefers-reduced-motion: no-preference)` or provide reduced-motion alternatives
165- For `prefers-reduced-motion: reduce`, replace motion with instant state changes or subtle fades
166- Do not auto-play video or animations without a pause/stop control
167- Ensure parallax and scroll-triggered effects do not cause disorientation
168- Respect motion preferences in carousels, slideshows, and onboarding tours
169
170## Verify Improvements
171
172After remediation, verify that fixes work:
173
174- **Re-run automated checks**: confirm previous violations are resolved and no new ones were introduced
175- **Keyboard pass**: tab through every interactive element again
176- **Screen reader pass**: navigate by headings, landmarks, and form fields
177- **Zoom test**: confirm usability at 200% and 400%
178- **Color-vision simulation**: confirm states and charts remain distinguishable
179- **Reduced motion**: enable `prefers-reduced-motion` and confirm the interface is still usable
180- **Real devices**: test on actual assistive technology when possible
181
182## Practical Checklist
183
184- [ ] All interactive elements are reachable by keyboard
185- [ ] Focus order is logical and predictable
186- [ ] Focus indicators are visible
187- [ ] Native HTML elements are used where possible
188- [ ] ARIA is used only when HTML is insufficient
189- [ ] Custom components have appropriate keyboard handlers
190- [ ] Color contrast meets WCAG AA (4.5:1 for text)
191- [ ] Color is not the only signal for state or meaning
192- [ ] Images have descriptive alt text (decorative images are marked as such)
193- [ ] Form inputs have associated labels
194- [ ] Form errors are linked to fields and announced
195- [ ] Dynamic content changes use aria-live regions
196- [ ] Touch targets are at least 44 by 44 pixels
197- [ ] Interface remains usable at 200% zoom
198- [ ] Motion respects `prefers-reduced-motion`
199- [ ] Automated tests pass with no WCAG AA violations
200- [ ] Manual keyboard and screen reader tests pass
201
202**NEVER**:
203- Rely on automated testing alone
204- Use ARIA without implementing corresponding keyboard behavior
205- Rely on color alone for important information
206- Remove focus indicators without providing a replacement
207- Skip manual testing with real assistive technology for critical flows
208- Treat accessibility as a one-time fix rather than an ongoing practice
209
210Remember: accessible design is usable design. Fixing accessibility issues usually improves the experience for everyone.