auditing-accessibility-wcag

Checks components and pages for WCAG 2.1 accessibility violations. Use when the user asks about a11y, WCAG compliance, screen readers, aria labels, keyboard navigation, or accessible patterns.

16 stars

Best use case

auditing-accessibility-wcag is best used when you need a repeatable AI agent workflow instead of a one-off prompt.

Checks components and pages for WCAG 2.1 accessibility violations. Use when the user asks about a11y, WCAG compliance, screen readers, aria labels, keyboard navigation, or accessible patterns.

Teams using auditing-accessibility-wcag should expect a more consistent output, faster repeated execution, less prompt rewriting.

When to use this skill

  • You want a reusable workflow that can be run more than once with consistent structure.

When not to use this skill

  • You only need a quick one-off answer and do not need a reusable workflow.
  • You cannot install or maintain the underlying files, dependencies, or repository context.

Installation

Claude Code / Cursor / Codex

$curl -o ~/.claude/skills/auditing-accessibility-wcag/SKILL.md --create-dirs "https://raw.githubusercontent.com/diegosouzapw/awesome-omni-skill/main/skills/testing-security/auditing-accessibility-wcag/SKILL.md"

Manual Installation

  1. Download SKILL.md from GitHub
  2. Place it in .claude/skills/auditing-accessibility-wcag/SKILL.md inside your project
  3. Restart your AI agent — it will auto-discover the skill

How auditing-accessibility-wcag Compares

Feature / Agentauditing-accessibility-wcagStandard Approach
Platform SupportNot specifiedLimited / Varies
Context Awareness High Baseline
Installation ComplexityUnknownN/A

Frequently Asked Questions

What does this skill do?

Checks components and pages for WCAG 2.1 accessibility violations. Use when the user asks about a11y, WCAG compliance, screen readers, aria labels, keyboard navigation, or accessible patterns.

Where can I find the source code?

You can find the source code on GitHub using the link provided at the top of the page.

SKILL.md Source

# Accessibility Auditor (WCAG 2.1)

## When to use this skill

- User asks about accessibility or a11y
- User mentions WCAG or compliance levels
- User wants to audit a component or page
- User asks about aria labels or roles
- User needs accessible alternative patterns

## Workflow

- [ ] Identify scope (component, page, site)
- [ ] Run automated audits
- [ ] Review manual checkpoints
- [ ] Categorize violations by severity
- [ ] Provide remediation examples
- [ ] Validate fixes

## Instructions

### Step 1: Run Automated Audits

**axe-core (CLI):**

```bash
npm install -D @axe-core/cli
npx axe http://localhost:3000 --exit
```

**Lighthouse accessibility audit:**

```bash
npx lighthouse http://localhost:3000 --only-categories=accessibility --output=json
```

**ESLint accessibility plugin:**

```bash
npm install -D eslint-plugin-jsx-a11y
```

```javascript
// eslint.config.js
import jsxA11y from "eslint-plugin-jsx-a11y";

export default [jsxA11y.flatConfigs.recommended];
```

### Step 2: WCAG 2.1 AA Checklist

| Principle      | Guideline             | Common Issues               |
| -------------- | --------------------- | --------------------------- |
| Perceivable    | 1.1 Text Alternatives | Missing alt text            |
| Perceivable    | 1.3 Adaptable         | Improper heading order      |
| Perceivable    | 1.4 Distinguishable   | Low color contrast          |
| Operable       | 2.1 Keyboard          | No focus styles             |
| Operable       | 2.4 Navigable         | Missing skip links          |
| Understandable | 3.1 Readable          | Missing lang attribute      |
| Understandable | 3.2 Predictable       | Unexpected focus changes    |
| Robust         | 4.1 Compatible        | Invalid HTML, missing roles |

### Step 3: Common Violations & Fixes

**Missing alt text:**

```tsx
// ❌ Violation
<img src="/hero.jpg" />

// ✅ Fixed - Informative image
<img src="/hero.jpg" alt="Team collaborating in modern office" />

// ✅ Fixed - Decorative image
<img src="/divider.svg" alt="" role="presentation" />
```

**Low color contrast (4.5:1 minimum for AA):**

```css
/* ❌ Violation - 2.5:1 ratio */
.text-muted {
  color: #999999;
  background: #ffffff;
}

/* ✅ Fixed - 4.6:1 ratio */
.text-muted {
  color: #767676;
  background: #ffffff;
}
```

**Missing form labels:**

```tsx
// ❌ Violation
<input type="email" placeholder="Email" />

// ✅ Fixed - Visible label
<label htmlFor="email">Email</label>
<input id="email" type="email" />

// ✅ Fixed - Visually hidden label
<label htmlFor="email" className="sr-only">Email</label>
<input id="email" type="email" placeholder="Email" />
```

**Missing focus indicators:**

```css
/* ❌ Violation */
button:focus {
  outline: none;
}

/* ✅ Fixed */
button:focus-visible {
  outline: 2px solid var(--color-primary);
  outline-offset: 2px;
}
```

**Improper heading hierarchy:**

```tsx
// ❌ Violation - Skips h2
<h1>Page Title</h1>
<h3>Section Title</h3>

// ✅ Fixed
<h1>Page Title</h1>
<h2>Section Title</h2>
```

**Non-semantic buttons:**

```tsx
// ❌ Violation
<div onClick={handleClick}>Click me</div>

// ✅ Fixed
<button type="button" onClick={handleClick}>Click me</button>
```

**Missing skip link:**

```tsx
// ✅ Add at top of page
<a href="#main-content" className="skip-link">
  Skip to main content
</a>

// ... header/nav ...

<main id="main-content">
  {/* Page content */}
</main>
```

```css
.skip-link {
  position: absolute;
  left: -9999px;
  z-index: 999;
  padding: 1rem;
  background: var(--color-background);
  color: var(--color-text);
}

.skip-link:focus {
  left: 1rem;
  top: 1rem;
}
```

### Step 4: Interactive Component Patterns

**Accessible modal:**

```tsx
import { useEffect, useRef } from "react";

interface ModalProps {
  isOpen: boolean;
  onClose: () => void;
  title: string;
  children: React.ReactNode;
}

export function Modal({ isOpen, onClose, title, children }: ModalProps) {
  const closeButtonRef = useRef<HTMLButtonElement>(null);
  const modalRef = useRef<HTMLDivElement>(null);

  useEffect(() => {
    if (isOpen) {
      closeButtonRef.current?.focus();
      document.body.style.overflow = "hidden";
    }
    return () => {
      document.body.style.overflow = "";
    };
  }, [isOpen]);

  // Trap focus inside modal
  const handleKeyDown = (e: React.KeyboardEvent) => {
    if (e.key === "Escape") onClose();
    if (e.key === "Tab") {
      const focusable = modalRef.current?.querySelectorAll<HTMLElement>(
        'button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])',
      );
      if (!focusable?.length) return;

      const first = focusable[0];
      const last = focusable[focusable.length - 1];

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

  if (!isOpen) return null;

  return (
    <div
      role="dialog"
      aria-modal="true"
      aria-labelledby="modal-title"
      ref={modalRef}
      onKeyDown={handleKeyDown}
    >
      <div className="modal-backdrop" onClick={onClose} aria-hidden="true" />
      <div className="modal-content">
        <h2 id="modal-title">{title}</h2>
        {children}
        <button ref={closeButtonRef} onClick={onClose} aria-label="Close modal">
          ×
        </button>
      </div>
    </div>
  );
}
```

**Accessible dropdown menu:**

```tsx
import { useState, useRef } from "react";

export function Dropdown({ label, items }: { label: string; items: string[] }) {
  const [isOpen, setIsOpen] = useState(false);
  const [activeIndex, setActiveIndex] = useState(-1);
  const buttonRef = useRef<HTMLButtonElement>(null);

  const handleKeyDown = (e: React.KeyboardEvent) => {
    switch (e.key) {
      case "ArrowDown":
        e.preventDefault();
        setActiveIndex((i) => Math.min(i + 1, items.length - 1));
        break;
      case "ArrowUp":
        e.preventDefault();
        setActiveIndex((i) => Math.max(i - 1, 0));
        break;
      case "Escape":
        setIsOpen(false);
        buttonRef.current?.focus();
        break;
      case "Enter":
      case " ":
        if (!isOpen) {
          setIsOpen(true);
          setActiveIndex(0);
        }
        break;
    }
  };

  return (
    <div onKeyDown={handleKeyDown}>
      <button
        ref={buttonRef}
        aria-expanded={isOpen}
        aria-haspopup="listbox"
        onClick={() => setIsOpen(!isOpen)}
      >
        {label}
      </button>
      {isOpen && (
        <ul role="listbox" aria-activedescendant={`item-${activeIndex}`}>
          {items.map((item, i) => (
            <li
              key={item}
              id={`item-${i}`}
              role="option"
              aria-selected={i === activeIndex}
            >
              {item}
            </li>
          ))}
        </ul>
      )}
    </div>
  );
}
```

### Step 5: Testing Tools

**Screen reader testing:**

- macOS: VoiceOver (Cmd+F5)
- Windows: NVDA (free) or JAWS
- Browser: ChromeVox extension

**Browser extensions:**

- axe DevTools
- WAVE Evaluation Tool
- Accessibility Insights

**Keyboard testing checklist:**

- [ ] All interactive elements reachable via Tab
- [ ] Focus order matches visual order
- [ ] Focus visible on all elements
- [ ] Escape closes modals/dropdowns
- [ ] Arrow keys navigate within components

### Step 6: Audit Report Template

```markdown
## Accessibility Audit Report

**URL**: https://example.com
**Date**: 2026-01-18
**Standard**: WCAG 2.1 AA
**Tools**: axe-core, Lighthouse, manual testing

### Summary

| Severity | Count |
| -------- | ----- |
| Critical | 2     |
| Serious  | 5     |
| Moderate | 8     |
| Minor    | 3     |

### Critical Issues

#### 1. Images missing alt text

- **WCAG**: 1.1.1 Non-text Content
- **Location**: Homepage hero, product cards
- **Impact**: Screen reader users cannot understand image content
- **Fix**: Add descriptive alt text to all informative images

#### 2. Form inputs missing labels

- **WCAG**: 1.3.1 Info and Relationships
- **Location**: Contact form, search box
- **Impact**: Users cannot identify form field purpose
- **Fix**: Associate `<label>` with each input via `for`/`id`

### Recommendations

1. Add eslint-plugin-jsx-a11y to catch issues during development
2. Include accessibility testing in CI pipeline
3. Train team on keyboard navigation testing
```

## Validation

Before completing:

- [ ] axe-core reports zero violations
- [ ] Lighthouse accessibility score ≥ 90
- [ ] Keyboard navigation works throughout
- [ ] Screen reader announces content correctly
- [ ] Color contrast meets 4.5:1 (text) / 3:1 (large text)
- [ ] Focus is visible on all interactive elements

## Error Handling

- **False positives**: Some automated tools flag valid patterns; verify manually.
- **Dynamic content**: Re-run audits after JavaScript loads; use axe-core in tests.
- **Third-party widgets**: Document inaccessible third-party components for vendor follow-up.
- **Complex widgets**: Reference WAI-ARIA Authoring Practices for correct patterns.

## Resources

- [WCAG 2.1 Quick Reference](https://www.w3.org/WAI/WCAG21/quickref/)
- [WAI-ARIA Authoring Practices](https://www.w3.org/WAI/ARIA/apg/)
- [axe-core Rules](https://dequeuniversity.com/rules/axe/)
- [A11y Project Checklist](https://www.a11yproject.com/checklist/)

Related Skills

Axe-core Accessibility

16
from diegosouzapw/awesome-omni-skill

Automated accessibility testing with axe-core and WCAG 2.1 compliance

agent-accessibility-tester

16
from diegosouzapw/awesome-omni-skill

Expert accessibility tester specializing in WCAG compliance, inclusive design, and universal access. Masters screen reader compatibility, keyboard navigation, and assistive technology integration with focus on creating barrier-free digital experiences.

accessibility-testing

16
from diegosouzapw/awesome-omni-skill

WCAG compliance testing and accessibility quality assurance workflows for iOS apps. Use when validating accessibility labels, testing VoiceOver compatibility, checking contrast ratios, or ensuring WCAG 2.1 compliance. Covers accessibility tree analysis, semantic validation, and automated accessibility testing patterns.

accessibility-tester

16
from diegosouzapw/awesome-omni-skill

Expert accessibility tester specializing in WCAG compliance, inclusive design, and universal access. Masters screen reader compatibility, keyboard navigation, and assistive technology integration with focus on creating barrier-free digital experiences.

accessibility-test-axe

16
from diegosouzapw/awesome-omni-skill

Эксперт по a11y тестированию. Используй для axe-core, automated testing и accessibility audits.

accessibility-planning

16
from diegosouzapw/awesome-omni-skill

Plan accessibility compliance - WCAG 2.2, Section 508, EN 301 549, inclusive design principles, audit planning, and remediation strategies.

accessibility-compliance-accessibility-audit

16
from diegosouzapw/awesome-omni-skill

You are an accessibility expert specializing in WCAG compliance, inclusive design, and assistive technology compatibility. Conduct audits, identify barriers, and provide remediation guidance.

accessibility-checker

16
from diegosouzapw/awesome-omni-skill

Validate WCAG 2.1 Level AA compliance and accessibility best practices. Use when performing accessibility audits and WCAG certification.

accessibility-check

16
from diegosouzapw/awesome-omni-skill

Run accessibility audit on frontend components for WCAG 2.1 AA compliance

Accessibility Auditor

16
from diegosouzapw/awesome-omni-skill

Web accessibility specialist for WCAG compliance, ARIA implementation, and inclusive design. Use when auditing websites for accessibility issues, implementing WCAG 2.1 AA/AAA standards, testing with screen readers, or ensuring ADA compliance. Expert in semantic HTML, keyboard navigation, and assistive technology compatibility.

accessibility-auditing

16
from diegosouzapw/awesome-omni-skill

Guide for conducting comprehensive accessibility audits of code to identify WCAG compliance issues and barriers to inclusive design. This skill should be used when reviewing accessibility, ARIA implementation, keyboard navigation, or screen reader compatibility.

accessibility-audit

16
from diegosouzapw/awesome-omni-skill

Fast, high-signal accessibility triage for pages, components, or PRs targeting WCAG 2.2 AA compliance.