Skills DirectorySkills Directory
SkillsLearnSecurityCategoriesDocsCommunityBlog
Sign InSubmit Skill
Skills Directory

Security-tested agent skills for Claude, coding agents, and AI workflows.

Directory

  • Browse Skills
  • All Skills A–Z
  • Claude Skills
  • Claude Code Skills
  • Agent Skills
  • Categories
  • Submit a Skill

Learn

  • Learn Hub
  • Install Claude Skills
  • Write SKILL.md
  • Skills vs MCP
  • Directories Compared

Security

  • Security
  • Methodology
  • Secure Claude Skills
  • Security Badges

Company

  • About
  • Community
  • Blog
  • API Docs
  • Advertise

2026 Skills Directory. All rights reserved.

Back to skills

Accessibility A11y Skill

ASecurity

Implement and audit web accessibility — WCAG 2.1, ARIA, keyboard navigation, contrast, screen readers, axe-core/Lighthouse audits, semantic HTML, focus management.

6 stars
0 votes
0 copies
0 views
Added 9/20/2026
developmentjavascripttypescriptgojavanextjsawstestingfrontendci/cdsecurity

Works with

cli

Security Analysis

A100/100

Scanned 9/20/2026

Install to Claude Code

$npx -y skills add darellchua2/opencode-config-template --skill accessibility-a11y-skill --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Accessibility A11y Skill?

Add the live security badge to your README — it updates automatically with every re-scan.

Security grade badge for Accessibility A11y Skill
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/darellchua2-accessibility-a11y-skill/badge)](https://www.skillsdirectory.com/skills/darellchua2-accessibility-a11y-skill)

More formats (shields.io, HTML) on the badges page.

Download Zip
Files
SKILL.md
---
name: accessibility-a11y-skill
description: >-
  Implement and audit web accessibility — WCAG 2.1, ARIA, keyboard navigation,
  contrast, screen readers, axe-core/Lighthouse audits, semantic HTML, focus
  management.
license: Apache-2.0
compatibility: opencode
category: Framework-Specific
---

## What I do

I help you build accessible web applications that work for everyone:

1. **WCAG 2.1 Compliance**: Systematic review against A/AA/AAA criteria
2. **ARIA Patterns**: Correct use of roles, states, and properties
3. **Keyboard Navigation**: Focus management and keyboard shortcuts
4. **Color Contrast**: Verify contrast ratios and color independence
5. **Automated Audits**: Configure axe-core and Lighthouse in CI
6. **Semantic HTML**: Proper element selection for meaning and structure
7. **Screen Reader Testing**: Testing strategies for NVDA, VoiceOver, JAWS

## When to use me

Use this skill when:
- Building UI components that must be accessible
- Auditing an existing application for WCAG compliance
- Setting up automated accessibility testing in CI/CD
- Implementing keyboard navigation for complex widgets
- Fixing accessibility violations reported by Lighthouse or axe-core
- Creating ARIA patterns for custom components
- Ensuring color contrast meets WCAG requirements
- Adding screen reader support to dynamic content

## Related Skills

- **frontend-design-skill**: UI creation and visual design. This skill ensures that UI is accessible.
- **uiux-review-skill**: Peer — surfaces a11y basics at axis 10 of its 13-axis rubric (alt text, labels, contrast samples, axe-core checks) and **delegates deep WCAG 2.1 compliance work here**. If a UI/UX review surfaces a Critical a11y finding, follow up with this skill for the full fix pattern.
- **nextjs-standard-setup-skill**: Project scaffolding. This skill adds accessibility to the built components.
- **testing-subagent**: Can generate accessibility-specific tests.

---

## Step 1: Semantic HTML

### Document Structure

```html
<header role="banner">
  <nav aria-label="Main navigation">
    <ul>
      <li><a href="/" aria-current="page">Home</a></li>
      <li><a href="/about">About</a></li>
      <li><a href="/contact">Contact</a></li>
    </ul>
  </nav>
</header>

<main id="main-content">
  <h1>Page Title</h1>
  <section aria-labelledby="features-heading">
    <h2 id="features-heading">Features</h2>
    <article>
      <h3>Feature One</h3>
      <p>Description of feature one.</p>
    </article>
  </section>
</main>

<footer role="contentinfo">
  <p>&copy; 2024 Company Name</p>
</footer>
```

### Element Selection Rules

| Use | Instead Of | Why |
|-----|-----------|-----|
| `<button>` | `<div onclick>` | Native focus, keyboard, semantics |
| `<a href>` | `<span onclick>` | Native link behavior |
| `<input type="checkbox">` | Styled `<div>` | Native form control |
| `<label>` | Placeholder text | Always visible label |
| `<fieldset>` + `<legend>` | Grouped `<div>` | Form group semantics |
| `<table>` with `<th>` | CSS grid for data | Table semantics |
| `<dialog>` | Custom modal | Native focus trap, escape |

---

## Step 2: ARIA Patterns

### Rules of ARIA

1. **Don't use ARIA** if a native HTML element provides the semantics
2. **Don't change native semantics** — use `<button>` not `<div role="button">`
3. **All interactive ARIA elements must be keyboard accessible**
4. **Don't use `role="presentation"` or `aria-hidden="true"`** on focusable elements

### Common Patterns

#### Live Regions (Dynamic Content)

```html
<div aria-live="polite" aria-atomic="true">
  <p>3 results found</p>
</div>

<div aria-live="assertive" role="alert">
  <p>Form submission failed. Please check your inputs.</p>
</div>
```

#### Dynamic Error Banners (`aria-alert-dynamic-errors`)

Conditionally rendered error banners are invisible to screen readers unless announced via `role="alert"`. Icon-only dismiss buttons need an explicit `aria-label`.

```tsx
// BEFORE: Error banner not announced, dismiss button has no label
{error && (
  <div className="rounded-md bg-red-50 p-4">
    <p className="text-sm text-red-700">{error}</p>
    <button onClick={() => setError(null)}>
      <XIcon className="h-5 w-5 text-red-500" />
    </button>
  </div>
)}

// AFTER: role="alert" announces changes, aria-label on dismiss button
{error && (
  <div role="alert" className="rounded-md bg-red-50 p-4">
    <p className="text-sm text-red-700">{error}</p>
    <button
      onClick={() => setError(null)}
      aria-label="Dismiss error"
      className="ml-2 text-red-500 hover:text-red-700"
    >
      <XIcon className="h-5 w-5" />
    </button>
  </div>
)}
```

**Key points**:
- `role="alert"` makes the container a live assertive region — screen readers announce content immediately on render
- Icon-only buttons require `aria-label` describing the action (e.g., "Dismiss error", "Close notification")
- Do NOT place `role="alert"` on a permanently visible container — only on dynamically shown/hidden content

#### Disclosure/Accordion

```html
<h3>
  <button
    aria-expanded="false"
    aria-controls="section-1"
    id="section-1-trigger"
  >
    Section Title
  </button>
</h3>
<div
  id="section-1"
  role="region"
  aria-labelledby="section-1-trigger"
  hidden
>
  <p>Section content</p>
</div>
```

```typescript
function toggleDisclosure(trigger: HTMLButtonElement) {
  const expanded = trigger.getAttribute("aria-expanded") === "true"
  const content = document.getElementById(trigger.getAttribute("aria-controls")!)

  trigger.setAttribute("aria-expanded", String(!expanded))
  content.hidden = expanded
}
```

#### Dialog/Modal

```html
<dialog aria-labelledby="dialog-title" aria-describedby="dialog-desc">
  <h2 id="dialog-title">Confirm Action</h2>
  <p id="dialog-desc">Are you sure you want to delete this item?</p>
  <button>Cancel</button>
  <button>Confirm</button>
</dialog>
```

#### Tabs

```html
<div role="tablist" aria-label="Account settings">
  <button role="tab" aria-selected="true" aria-controls="panel-profile" id="tab-profile">
    Profile
  </button>
  <button role="tab" aria-selected="false" aria-controls="panel-security" id="tab-security" tabindex="-1">
    Security
  </button>
</div>
<div role="tabpanel" aria-labelledby="tab-profile" id="panel-profile">
  <p>Profile settings</p>
</div>
<div role="tabpanel" aria-labelledby="tab-security" id="panel-security" hidden>
  <p>Security settings</p>
</div>
```

---

## Step 3: Keyboard Navigation

### Focus Management

```typescript
function trapFocus(container: HTMLElement) {
  const focusable = container.querySelectorAll<HTMLElement>(
    'a[href], button:not([disabled]), input:not([disabled]), select:not([disabled]), textarea:not([disabled]), [tabindex]:not([tabindex="-1"])'
  )
  const first = focusable[0]
  const last = focusable[focusable.length - 1]

  container.addEventListener("keydown", (e) => {
    if (e.key !== "Tab") return

    if (e.shiftKey) {
      if (document.activeElement === first) {
        e.preventDefault()
        last.focus()
      }
    } else {
      if (document.activeElement === last) {
        e.preventDefault()
        first.focus()
      }
    }
  })

  first.focus()
}
```

### Skip Navigation

```html
<a href="#main-content" class="sr-only focus:not-sr-only focus:absolute focus:top-4 focus:left-4 focus:z-50 focus:px-4 focus:py-2 focus:bg-white focus:text-black">
  Skip to main content
</a>
```

### Keyboard Shortcuts Table

| Key | Action |
|-----|--------|
| Tab | Move to next focusable element |
| Shift+Tab | Move to previous focusable element |
| Enter | Activate button or link |
| Space | Activate button, toggle checkbox |
| Escape | Close modal, cancel action |
| Arrow keys | Navigate tabs, menus, listboxes |
| Home/End | First/last item in group |

---

## Step 4: Color Contrast

### WCAG Requirements

| Level | Normal Text | Large Text (18pt+/14pt bold) | UI Components |
|-------|-------------|-------------------------------|---------------|
| AA | 4.5:1 | 3:1 | 3:1 |
| AAA | 7:1 | 4.5:1 | Not specified |

### Tailwind Contrast Utilities

```css
.text-primary-900.bg-primary-50 { /* 18:1 contrast ratio */ }
.text-gray-700.bg-white { /* 8.5:1 contrast ratio */ }
.text-gray-400.bg-white { /* 2.8:1 — FAILS AA */ }
```

### Don't Rely on Color Alone

```html
<div class="flex items-center gap-2">
  <span class="inline-block w-3 h-3 rounded-full bg-green-500" aria-hidden="true"></span>
  <span class="text-green-700">
    <svg class="inline w-4 h-4" aria-hidden="true"><path d="M5 13l4 4L19 7" /></svg>
    Active
  </span>
</div>

<div class="flex items-center gap-2">
  <span class="inline-block w-3 h-3 rounded-full bg-red-500" aria-hidden="true"></span>
  <span class="text-red-700">
    <svg class="inline w-4 h-4" aria-hidden="true"><path d="M6 18L18 6M6 6l12 12" /></svg>
    Error
  </span>
</div>
```

---

## Step 5: Automated Audits

### axe-core with Jest

```typescript
import { axe, toHaveNoViolations } from "jest-axe"

expect.extend(toHaveNoViolations)

test("button has no accessibility violations", async () => {
  const { container } = render(<Button>Click me</Button>)
  const results = await axe(container)
  expect(results).toHaveNoViolations()
})
```

### Lighthouse CI

```yaml
name: Accessibility Audit
on: [push]
jobs:
  lighthouse:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: treosh/lighthouse-ci-action@v12
        with:
          urls: |
            http://localhost:3000
          uploadArtifacts: true
          budgetPath: ./lighthouse-budget.json
```

### Lighthouse Budget

```json
{
  "ci": {
    "assert": {
      "assertions": {
        "categories:accessibility": ["error", { "minScore": 0.9 }],
        "color-contrast": "error",
        "document-title": "error",
        "html-has-lang": "error",
        "meta-viewport": "error",
        "valid-lang": "warn"
      }
    }
  }
}
```

### Next.js eslint-plugin-jsx-a11y

```javascript
module.exports = {
  extends: ["next/core-web-vitals", "plugin:jsx-a11y/recommended"],
  plugins: ["jsx-a11y"],
  rules: {
    "jsx-a11y/alt-text": "error",
    "jsx-a11y/anchor-is-valid": "error",
    "jsx-a11y/aria-props": "error",
    "jsx-a11y/aria-role": "error",
    "jsx-a11y/aria-unsupported-elements": "error",
    "jsx-a11y/click-events-have-key-events": "warn",
    "jsx-a11y/label-has-associated-control": "error",
    "jsx-a11y/mouse-events-have-key-events": "warn",
    "jsx-a11y/no-autofocus": "error",
    "jsx-a11y/no-static-element-interactions": "warn",
    "jsx-a11y/role-has-required-aria-props": "error",
  },
}
```

---

## Step 6: WCAG 2.1 Quick Checklist

### Perceivable

- [ ] All images have meaningful `alt` text
- [ ] Video has captions and audio has transcripts
- [ ] Color contrast meets AA (4.5:1 text, 3:1 large text)
- [ ] Information not conveyed by color alone
- [ ] Content resizes to 200% without loss

### Operable

- [ ] All functionality available via keyboard
- [ ] Focus indicator visible
- [ ] Skip navigation link provided
- [ ] No keyboard traps
- [ ] Enough time to read content (or extendable)
- [ ] No content flashes more than 3 times per second

### Understandable

- [ ] Language defined (`<html lang="en">`)
- [ ] Form labels associated with inputs
- [ ] Error messages clearly identify the problem and suggest fixes
- [ ] Navigation consistent across pages
- [ ] Predictable behavior on focus and input

### Robust

- [ ] Valid HTML markup
- [ ] ARIA used correctly (if needed)
- [ ] Name, role, value defined for all UI components
- [ ] Status messages announced to screen readers

Attribution

darellchua2darellchua2
View sourceMore from darellchua2 →
SSkills DirectorySkills Directory

Your tool, in front of Claude Code builders.

3 founder slots · $299/mo · GSC-verified traffic · sponsors can never buy grades.

See placements

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments (0)

No comments yet. Be the first to comment!

SSkills DirectorySkills Directory

Your tool, in front of Claude Code builders.

3 founder slots · $299/mo · GSC-verified traffic · sponsors can never buy grades.

See placements

Related Skills

Browser Extension Developer

Use this skill when developing or maintaining browser extension code in the `browser/` directory, including Chrome/Firefox/Edge compatibility, content scripts, background scripts, or i18n updates.

281612 votes

Seo Optimizer

SEO optimization with keyword analysis, readability assessment, technical validation, content quality. Use for search rankings, blog posts, content audits, or encountering keyword density, readability scores, meta tags, schema markup errors.

2132 votes

Google Official Seo Guide

Official Google SEO guide covering search optimization, best practices, Search Console, crawling, indexing, and improving website search visibility based on official Google documentation

1862 votes

Tanstack Start

Build a full-stack TanStack Start app on Cloudflare Workers from scratch — SSR, file-based routing, server functions, D1+Drizzle, better-auth, Tailwind v4+shadcn/ui. Use whenever the user mentions TanStack Start, asks to scaffold a full-stack Cloudflare app with SSR, wants an SSR dashboard, or asks for a React 19 + Cloudflare Workers app with file-based routing and server functions — even if they don't name TanStack Start specifically. No template repo — Claude generates every file fresh per ...

9881 votes

Pentest

PTES-aligned adversarial security audit for backend, frontend, and mobile applications. Produces a CVSS-scored Hacker Report with verified PoCs and phased remediation.

5491 votes
View all in development →