Claude Agent Skill · by Addyosmani

Accessibility

The accessibility skill audits and improves web accessibility by providing comprehensive guidance on WCAG 2.2 compliance, including best practices for text alte

Install
Terminal · npx
$npx skills add https://github.com/addyosmani/web-quality-skills --skill accessibility
Works with Paperclip

How Accessibility fits into a Paperclip company.

Accessibility drops into any Paperclip agent that handles this kind of work. Assign it to a specialist inside a pre-configured PaperclipOrg company and the skill becomes available on every heartbeat — no prompt engineering, no tool wiring.

S
SaaS FactoryPaired

Pre-configured AI company — 18 agents, 18 skills, one-time purchase.

$27$59
Explore pack
Source file
SKILL.md440 lines
Expand
---name: accessibilitydescription: Audit and improve web accessibility following WCAG 2.2 guidelines. Use when asked to "improve accessibility", "a11y audit", "WCAG compliance", "screen reader support", "keyboard navigation", or "make accessible".license: MITmetadata:  author: web-quality-skills  version: "1.1"--- # Accessibility (a11y) Comprehensive accessibility guidelines based on WCAG 2.2 and Lighthouse accessibility audits. Goal: make content usable by everyone, including people with disabilities. ## WCAG Principles: POUR | Principle | Description ||-----------|-------------|| **P**erceivable | Content can be perceived through different senses || **O**perable | Interface can be operated by all users || **U**nderstandable | Content and interface are understandable || **R**obust | Content works with assistive technologies | ## Conformance levels | Level | Requirement | Target ||-------|-------------|--------|| **A** | Minimum accessibility | Must pass || **AA** | Standard compliance | Should pass (legal requirement in many jurisdictions) || **AAA** | Enhanced accessibility | Nice to have | --- ## Perceivable ### Text alternatives (1.1) **Images require alt text:**```html<!-- ❌ Missing alt --><img src="chart.png"> <!-- ✅ Descriptive alt --><img src="chart.png" alt="Bar chart showing 40% increase in Q3 sales"> <!-- ✅ Decorative image (empty alt) --><img src="decorative-border.png" alt="" role="presentation"> <!-- ✅ Complex image with longer description --><figure>  <img src="infographic.png" alt="2024 market trends infographic"        aria-describedby="infographic-desc">  <figcaption id="infographic-desc">    <!-- Detailed description -->  </figcaption></figure>``` **Icon buttons need accessible names:**```html<!-- ❌ No accessible name --><button><svg><!-- menu icon --></svg></button> <!-- ✅ Using aria-label --><button aria-label="Open menu">  <svg aria-hidden="true"><!-- menu icon --></svg></button> <!-- ✅ Using visually hidden text --><button>  <svg aria-hidden="true"><!-- menu icon --></svg>  <span class="visually-hidden">Open menu</span></button>``` **Visually hidden class:**```css.visually-hidden {  position: absolute;  width: 1px;  height: 1px;  padding: 0;  margin: -1px;  overflow: hidden;  clip: rect(0, 0, 0, 0);  white-space: nowrap;  border: 0;}``` ### Color contrast (1.4.3, 1.4.6) | Text Size | AA minimum | AAA enhanced ||-----------|------------|--------------|| Normal text (< 18px / < 14px bold) | 4.5:1 | 7:1 || Large text (≥ 18px / ≥ 14px bold) | 3:1 | 4.5:1 || UI components & graphics | 3:1 | 3:1 | ```css/* ❌ Low contrast (2.5:1) */.low-contrast {  color: #999;  background: #fff;} /* ✅ Sufficient contrast (7:1) */.high-contrast {  color: #333;  background: #fff;} /* ✅ Focus states need contrast too */:focus-visible {  outline: 2px solid #005fcc;  outline-offset: 2px;}``` **Don't rely on color alone:**```html<!-- ❌ Only color indicates error --><input class="error-border"><style>.error-border { border-color: red; }</style> <!-- ✅ Color + icon + text --><div class="field-error">  <input aria-invalid="true" aria-describedby="email-error">  <span id="email-error" class="error-message">    <svg aria-hidden="true"><!-- error icon --></svg>    Please enter a valid email address  </span></div>``` ### Media alternatives (1.2) ```html<!-- Video with captions --><video controls>  <source src="video.mp4" type="video/mp4">  <track kind="captions" src="captions.vtt" srclang="en" label="English" default>  <track kind="descriptions" src="descriptions.vtt" srclang="en" label="Descriptions"></video> <!-- Audio with transcript --><audio controls>  <source src="podcast.mp3" type="audio/mp3"></audio><details>  <summary>Transcript</summary>  <p>Full transcript text...</p></details>``` --- ## Operable ### Keyboard accessible (2.1) **All functionality must be keyboard accessible:**```javascript// ❌ Only handles clickelement.addEventListener('click', handleAction); // ✅ Handles both click and keyboardelement.addEventListener('click', handleAction);element.addEventListener('keydown', (e) => {  if (e.key === 'Enter' || e.key === ' ') {    e.preventDefault();    handleAction();  }});``` **No keyboard traps.** Users must be able to Tab into and out of every component. Use the [modal focus trap pattern](references/A11Y-PATTERNS.md#modal-focus-trap) for dialogs—the native `<dialog>` element handles this automatically. ### Focus visible (2.4.7) ```css/* ❌ Never remove focus outlines */*:focus { outline: none; } /* ✅ Use :focus-visible for keyboard-only focus */:focus {  outline: none;} :focus-visible {  outline: 2px solid #005fcc;  outline-offset: 2px;} /* ✅ Or custom focus styles */button:focus-visible {  box-shadow: 0 0 0 3px rgba(0, 95, 204, 0.5);}``` ### Focus not obscured (2.4.11) — new in 2.2 When an element receives keyboard focus, it must not be entirely hidden by other author-created content such as sticky headers, footers, or overlapping panels. At Level AAA (2.4.12), no part of the focused element may be hidden. ```css/* ✅ Account for sticky headers when scrolling to focused elements */:target {  scroll-margin-top: 80px;} /* ✅ Ensure focused items clear fixed/sticky bars */:focus {  scroll-margin-top: 80px;  scroll-margin-bottom: 60px;}``` ### Skip links (2.4.1) Provide a skip link so keyboard users can bypass repetitive navigation. See the [skip link pattern](references/A11Y-PATTERNS.md#skip-link) for full markup and styles. ### Target size (2.5.8) — new in 2.2 Interactive targets must be at least **24 × 24 CSS pixels** (AA). Exceptions: inline text links, elements where the browser controls the size, and targets where a 24px circle centered on the bounding box does not overlap another target. ```css/* ✅ Minimum target size */button,[role="button"],input[type="checkbox"] + label,input[type="radio"] + label {  min-width: 24px;  min-height: 24px;} /* ✅ Comfortable target size (recommended 44×44) */.touch-target {  min-width: 44px;  min-height: 44px;  display: inline-flex;  align-items: center;  justify-content: center;}``` ### Dragging movements (2.5.7) — new in 2.2 Any action that requires dragging must have a single-pointer alternative (e.g., buttons, inputs). See the [dragging movements pattern](references/A11Y-PATTERNS.md#dragging-movements) for a sortable-list example. ### Timing (2.2) ```javascript// Allow users to extend time limitsfunction showSessionWarning() {  const modal = createModal({    title: 'Session Expiring',    content: 'Your session will expire in 2 minutes.',    actions: [      { label: 'Extend session', action: extendSession },      { label: 'Log out', action: logout }    ],    timeout: 120000  });}``` ### Motion (2.3) ```css/* Respect reduced motion preference */@media (prefers-reduced-motion: reduce) {  *,  *::before,  *::after {    animation-duration: 0.01ms !important;    animation-iteration-count: 1 !important;    transition-duration: 0.01ms !important;    scroll-behavior: auto !important;  }}``` --- ## Understandable ### Page language (3.1.1) ```html<!-- ❌ No language specified --><html> <!-- ✅ Language specified --><html lang="en"> <!-- ✅ Language changes within page --><p>The French word for hello is <span lang="fr">bonjour</span>.</p>``` ### Consistent navigation (3.2.3) ```html<!-- Navigation should be consistent across pages --><nav aria-label="Main">  <ul>    <li><a href="/" aria-current="page">Home</a></li>    <li><a href="/products">Products</a></li>    <li><a href="/about">About</a></li>  </ul></nav>``` ### Consistent help (3.2.6) — new in 2.2 If a help mechanism (contact info, chat widget, FAQ link, self-help option) is repeated across multiple pages, it must appear in the **same relative order** each time. Users who rely on consistent placement shouldn't have to hunt for help on every page. ### Form labels (3.3.2) Every input needs a programmatically associated label. See the [form labels pattern](references/A11Y-PATTERNS.md#form-labels) for explicit, implicit, and instructional examples. ### Error handling (3.3.1, 3.3.3) Announce errors to screen readers with `role="alert"` or `aria-live`, set `aria-invalid="true"` on invalid fields, and focus the first error on submit. See the [error handling pattern](references/A11Y-PATTERNS.md#error-handling) for full markup and JS. ### Redundant entry (3.3.7) — new in 2.2 Don't force users to re-enter information they already provided in the same session. Auto-populate from earlier steps, or let users select from previously entered values. Exceptions: security re-confirmation and content that has expired. ```html<!-- ✅ Auto-fill shipping address from billing --><fieldset>  <legend>Shipping address</legend>  <label>    <input type="checkbox" id="same-as-billing" checked>    Same as billing address  </label>  <!-- Fields auto-populated when checked --></fieldset>``` ### Accessible authentication (3.3.8) — new in 2.2 Login flows must not rely on cognitive function tests (e.g., remembering a password, solving a puzzle) unless at least one of:- A copy-paste or autofill mechanism is available- An alternative method exists (e.g., passkey, SSO, email link)- The test uses object recognition or personal content (AA only; AAA removes this exception) ```html<!-- ✅ Allow paste in password fields --><input type="password" id="password" autocomplete="current-password"> <!-- ✅ Offer passwordless alternatives --><button type="button">Sign in with passkey</button><button type="button">Email me a login link</button>``` --- ## Robust ### ARIA usage (4.1.2) **Prefer native elements:**```html<!-- ❌ ARIA role on div --><div role="button" tabindex="0">Click me</div> <!-- ✅ Native button --><button>Click me</button> <!-- ❌ ARIA checkbox --><div role="checkbox" aria-checked="false">Option</div> <!-- ✅ Native checkbox --><label><input type="checkbox"> Option</label>``` **When ARIA is needed,** use the correct roles and states. See the [ARIA tabs pattern](references/A11Y-PATTERNS.md#aria-tabs) for a complete tablist example. ### Live regions (4.1.3) Use `aria-live` regions to announce dynamic content changes without moving focus. See the [live regions pattern](references/A11Y-PATTERNS.md#live-regions-and-notifications) for markup and a `showNotification()` helper. --- ## Testing checklist ### Automated testing```bash# Lighthouse accessibility auditnpx lighthouse https://example.com --only-categories=accessibility # axe-corenpm install @axe-core/cli -gaxe https://example.com``` ### Manual testing - [ ] **Keyboard navigation:** Tab through entire page, use Enter/Space to activate- [ ] **Screen reader:** Test with VoiceOver (Mac), NVDA (Windows), or TalkBack (Android)- [ ] **Zoom:** Content usable at 200% zoom- [ ] **High contrast:** Test with Windows High Contrast Mode- [ ] **Reduced motion:** Test with `prefers-reduced-motion: reduce`- [ ] **Focus order:** Logical and follows visual order- [ ] **Target size:** Interactive elements meet 24×24px minimum See the [screen reader commands reference](references/A11Y-PATTERNS.md#screen-reader-commands) for VoiceOver and NVDA shortcuts. --- ## Common issues by impact ### Critical (fix immediately)1. Missing form labels2. Missing image alt text3. Insufficient color contrast4. Keyboard traps5. No focus indicators ### Serious (fix before launch)1. Missing page language2. Missing heading structure3. Non-descriptive link text4. Auto-playing media5. Missing skip links ### Moderate (fix soon)1. Missing ARIA labels on icons2. Inconsistent navigation3. Missing error identification4. Timing without controls5. Missing landmark regions ## References - [WCAG 2.2 Quick Reference](https://www.w3.org/WAI/WCAG22/quickref/)- [WAI-ARIA Authoring Practices](https://www.w3.org/WAI/ARIA/apg/)- [Deque axe Rules](https://dequeuniversity.com/rules/axe/)- [Web Quality Audit](../web-quality-audit/SKILL.md)- [WCAG criteria reference](references/WCAG.md)- [Accessibility code patterns](references/A11Y-PATTERNS.md)