All skills
addyosmani avatar

/accessibility

@c6b06ad official

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".

Use this Skill: https://skilld.dev/gh/addyosmani/web-quality-skills/accessibility

This session only. Nothing lands on disk.

referencesA11Y-PATTERNS.md

≈1.5k tokens on demand. Your agent reads this file only when SKILL.md points to it.

Accessibility Code Patterns

Practical, copy-paste-ready patterns for common accessibility requirements. Each pattern is self-contained and linked from the main SKILL.md.


Modal focus trap

Trap keyboard focus inside a modal dialog so Tab/Shift+Tab cycle through its focusable elements and Escape closes it.

function openModal(modal) {
  const focusableElements = modal.querySelectorAll(
    'button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])'
  );
  const firstElement = focusableElements[0];
  const lastElement = focusableElements[focusableElements.length - 1];

  modal.addEventListener('keydown', (e) => {
    if (e.key === 'Tab') {
      if (e.shiftKey && document.activeElement === firstElement) {
        e.preventDefault();
        lastElement.focus();
      } else if (!e.shiftKey && document.activeElement === lastElement) {
        e.preventDefault();
        firstElement.focus();
      }
    }
    if (e.key === 'Escape') {
      closeModal();
    }
  });

  firstElement.focus();
}

The native <dialog> element handles focus trapping automatically—prefer it when browser support allows.


Skip link

Allows keyboard users to bypass repetitive navigation and jump straight to main content.

<body>
  <a href="#main-content" class="skip-link">Skip to main content</a>
  <header><!-- navigation --></header>
  <main id="main-content" tabindex="-1">
    <!-- main content -->
  </main>
</body>
.skip-link {
  position: absolute;
  top: -40px;
  left: 0;
  background: #000;
  color: #fff;
  padding: 8px 16px;
  z-index: 100;
}

.skip-link:focus {
  top: 0;
}

Error handling

Announce errors to screen readers and focus the first invalid field on submit.

<form novalidate>
  <div class="field" aria-live="polite">
    <label for="email">Email</label>
    <input type="email" id="email"
           aria-invalid="true"
           aria-describedby="email-error">
    <p id="email-error" class="error" role="alert">
      Please enter a valid email address (e.g., name@example.com)
    </p>
  </div>
</form>
form.addEventListener('submit', (e) => {
  const firstError = form.querySelector('[aria-invalid="true"]');
  if (firstError) {
    e.preventDefault();
    firstError.focus();

    const errorSummary = document.getElementById('error-summary');
    errorSummary.textContent =
      `${errors.length} errors found. Please fix them and try again.`;
    errorSummary.focus();
  }
});

Form labels

Every input needs an associated label—either explicit (for/id) or implicit (wrapping <label>).

<!-- ❌ No label association -->
<input type="email" placeholder="Email">

<!-- ✅ Explicit label -->
<label for="email">Email address</label>
<input type="email" id="email" name="email"
       autocomplete="email" required>

<!-- ✅ Implicit label -->
<label>
  Email address
  <input type="email" name="email" autocomplete="email" required>
</label>

<!-- ✅ With instructions -->
<label for="password">Password</label>
<input type="password" id="password"
       aria-describedby="password-requirements">
<p id="password-requirements">
  Must be at least 8 characters with one number.
</p>

Dragging movements

Any action triggered by dragging must offer a single-pointer alternative (WCAG 2.5.7).

<!-- ❌ Drag-only reorder -->
<ul class="sortable-list" draggable="true">
  <li>Item 1</li>
  <li>Item 2</li>
</ul>

<!-- ✅ Drag + button alternatives -->
<ul class="sortable-list">
  <li>
    <span>Item 1</span>
    <button aria-label="Move Item 1 up">↑</button>
    <button aria-label="Move Item 1 down">↓</button>
  </li>
  <li>
    <span>Item 2</span>
    <button aria-label="Move Item 2 up">↑</button>
    <button aria-label="Move Item 2 down">↓</button>
  </li>
</ul>

Also applies to sliders, map panning, colour pickers, and similar drag-based widgets—always provide an equivalent click/tap or keyboard path.


ARIA tabs

Tabs require role="tablist", role="tab", and role="tabpanel" with proper aria-selected, aria-controls, and keyboard support.

<div role="tablist" aria-label="Product information">
  <button role="tab" id="tab-1" aria-selected="true"
          aria-controls="panel-1">Description</button>
  <button role="tab" id="tab-2" aria-selected="false"
          aria-controls="panel-2" tabindex="-1">Reviews</button>
</div>
<div role="tabpanel" id="panel-1" aria-labelledby="tab-1">
  <!-- Panel content -->
</div>
<div role="tabpanel" id="panel-2" aria-labelledby="tab-2" hidden>
  <!-- Panel content -->
</div>

Arrow keys should move focus between tabs; the active tab receives tabindex="0" while inactive tabs use tabindex="-1".


Live regions and notifications

Use aria-live to announce dynamic content changes to screen readers without moving focus.

<!-- Status updates (polite — waits for pause in speech) -->
<div aria-live="polite" aria-atomic="true" class="status">
  <!-- Content updates announced to screen readers -->
</div>

<!-- Urgent alerts (assertive — interrupts) -->
<div role="alert" aria-live="assertive">
  <!-- Interrupts current announcement -->
</div>
function showNotification(message, type = 'polite') {
  const container = document.getElementById(`${type}-announcer`);
  container.textContent = '';
  requestAnimationFrame(() => {
    container.textContent = message;
  });
}

Clear the container before writing to ensure the same message triggers a new announcement.


Screen reader commands

Quick reference for the most common screen reader shortcuts.

Action VoiceOver (Mac) NVDA (Windows)
Start/Stop ⌘ + F5 Ctrl + Alt + N
Next item VO + → ↓
Previous item VO + ← ↑
Activate VO + Space Enter
Headings list VO + U, then arrows H / Shift + H
Links list VO + U K / Shift + K

Source: SKILL.md on GitHub

No alerts17d5 checks · Risk SAFE
  • Gen Agent Trust Hub17d

    The skill is a high-quality instructional resource for web accessibility auditing. It carries a low risk of indirect prompt injection because it is designed to ingest and process external web content and tool outputs to suggest code fixes. No malicious patterns, exfiltration, or obfuscation were detected.

  • Socket17d

    No alerts

  • Snyk17d

    Risk: LOW · No issues

  • Runlayer6mo

    2 files scanned · No issues

  • ZeroLeaks5mo

    1 finding · Score: 82/100

Signed by skilld at c6b06ad. This ties the file your Agent reads to that commit on GitHub. It does not review the instructions.

Last checked against GitHub last month.

Steadyupdated last month
metadata
{
  "author": "web-quality-skills",
  "version": "2.0"
}
  • wcag
  • a11y
  • accessibility
  • aria
  • keyboard-navigation
  • screen-reader
  • contrast
  • html
  • css

README badge

README badge for addyosmani/web-quality-skills/accessibility

Audits and improves web accessibility against WCAG 2.2 guidelines, covering perceivable, operable, understandable, and robust principles. Provides concrete patterns for alt text, color contrast, keyboard navigation, focus management, form labels, error handling, and ARIA usage, with automated and manual testing checklists.

Generated from the current SKILL.md.

Does this skill cover WCAG 2.2 or just earlier versions?
Yes, it covers WCAG 2.2 specifically, including new requirements like focus not obscured (2.4.11), target size (2.5.8), dragging movements (2.5.7), consistent help (3.2.6), redundant entry (3.3.7), and accessible authentication (3.3.8).
What conformance level should I target?
Level AA is the standard compliance target and a legal requirement in many jurisdictions. Level A is the minimum, and Level AAA is enhanced accessibility but not required.
Does this skill include code examples and patterns?
Yes, it includes HTML, CSS, and JavaScript examples for common patterns like keyboard handling, focus management, form labels, error handling, ARIA tabs, live regions, and skip links.
What testing tools does this skill recommend?
It recommends automated testing with Lighthouse accessibility audits and axe-core CLI, plus manual testing with screen readers (VoiceOver, NVDA, TalkBack) and keyboard navigation.
Does this cover native HTML elements or only ARIA?
It emphasizes native HTML elements (button, a, form controls, dialog) as the preferred approach and only recommends ARIA when native elements cannot be used.

Generated from the current SKILL.md. These answers refresh after source changes.