mcpField
W
web-accessibility-audit

web-accessibility-audit

github.com/warpdotdev测试与质量822206 次安装28 周前更新
代码仓库

关于 web-accessibility-audit

这项技能依据常见 WCAG 要求审查 Web 应用的无障碍性,结合自动化检查、代码检查、按严重性排序和手动测试指引,面向开发者与审计团队。

主要功能

  1. 01WCAG 问题清单
  2. 02自动化测试指引
  3. 03手动代码检查
  4. 04按严重性排序
  5. 05辅助技术测试指引

适用场景

  1. 01检查网站的 WCAG 问题
  2. 02排查键盘导航障碍
  3. 03检查表单、标签和对比度
  4. 04制定按优先级排序的修复步骤

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/warpdotdev/oz-skills --skill web-accessibility-audit

安装后在 Claude Code 中输入/web-accessibility-audit确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

references/
ARIA-patterns.md
grep-patterns.md
screen-reader-guide.md
WCAG-criteria.md
scripts/
run-eslint.sh

详细介绍

无障碍审查工具

审查 Web 应用是否符合 WCAG 2.0/2.1/2.2 标准,识别常见违规问题并提供可执行的修复步骤。

适用场景

  • 用户要求进行无障碍审查、a11y 检查或 WCAG 合规性评估
  • 用户提及无障碍问题、屏幕阅读器或键盘导航问题
  • 用户要求检查或改善残障人士的无障碍体验

WCAG 原则:POUR

原则描述
Perceivable(可感知)内容可通过不同感官感知
Operable(可操作)所有用户都能操作界面
Understandable(可理解)内容和界面易于理解
Robust(健壮)内容可与辅助技术配合使用

合规等级

等级要求目标
A最低无障碍要求必须通过
AA标准合规要求应通过(许多司法辖区的法律要求)
AAA增强无障碍要求有则更好

12 项最常见的 WCAG 违规问题

基于 WebAIM Million(2021)对排名前 100 万的网站进行分析的研究:

  1. 颜色对比度低(WCAG 1.4.3) - 86.4% 的网站

    • 文本对比度低于 4.5:1
    • 大号文本对比度低于 3:1
    • UI 组件对比度低于 3:1
  2. 缺少或不合适的替代文本(WCAG 1.1.1) - 60.6% 的网站

    • 图片没有 alt 属性
    • 替代文本包含“image”“picture”“photo”等词
    • 有意义的图片使用空 alt
  3. 缺少名称、角色或值(WCAG 4.1.2)

    • 交互元素没有无障碍名称
    • 自定义组件缺少恰当的 ARIA
    • 按钮、表单字段、自定义小部件
  4. 键盘导航失败(WCAG 2.1.1)

    • 元素使用 onClick,但无法通过键盘访问
    • 缺少焦点指示器
    • 键盘焦点被困住
  5. 表单控件未标注(WCAG 1.3.1、3.3.2) - 39.6% 的网站

    • 输入框没有 <label> 或 aria-label
    • 标签未通过程序关联
  6. 缺少语言属性(WCAG 3.1.1) - 28.9% 的网站

    • <html> 上没有 lang 属性
    • 外语段落缺少 lang 属性
  7. 标题结构不当(WCAG 1.3.1、2.4.6)

    • 跳过标题级别(h1 → h3)
    • 存在多个 h1 或没有 h1
    • 标题为空
  8. 链接为空或链接文本不佳(WCAG 2.4.4)

    • 链接文本为“click here”“here”“read more”
    • 链接为空或仅包含图标
  9. 缺少或不恰当的焦点指示器(WCAG 2.4.7)

    • CSS 移除了 outline,却没有提供替代样式
    • 焦点指示器对比度不足
  10. 过度使用或误用 ARIA(WCAG 4.1.2)

    • 原生 HTML 已可满足需求,却使用了不必要的 ARIA
    • 角色对应的 ARIA 属性无效
    • 缺少必需的 ARIA 属性
  11. 数据表格标记不充分(WCAG 1.3.1)

    • 表格中没有 <th> 元素
    • 缺少 scope 或 headers 属性
  12. 缺少媒体字幕(WCAG 1.2.1、1.2.2)

    • 视频没有字幕
    • 音频没有文字稿

审查流程

阶段 1:自动化测试

运行 ESLint(React/JSX 项目):

npx eslint --ext .jsx,.tsx --no-ignore --format json . > .claude/skills/a11y-auditor/eslint-results.json 2>&1 || true

或使用辅助脚本:.claude/skills/a11y-auditor/scripts/run-eslint.sh

运行 Lighthouse(生产环境/预发布环境):

npx lighthouse https://example.com --only-categories=accessibility --output=json --output-path=./lighthouse-results.json

检查 axe-core 集成:

grep -r "@axe-core\|axe-core" package.json
阶段 2:手动检查代码

使用 references/grep-patterns.md 中的 grep 模式,搜索以下问题:

  • 缺少替代文本
  • 键盘导航问题
  • 用于检查对比度的颜色值
  • ARIA 问题
  • 表单标签
  • 标题结构
  • 语言属性
  • 不佳的链接文本
  • 媒体元素

完整的模式列表请参阅 references/grep-patterns.md。

阶段 3:分析并确定优先级

根据 WCAG 影响级别对发现的问题分组:

严重(立即修复):

  • 键盘陷阱
  • 没有焦点指示器
  • 缺少表单标签
  • 功能性图像缺少替代文本
  • 交互元素的颜色对比度不足

较严重(发布前修复):

  • 缺少页面语言
  • 标题结构不当
  • 链接文本缺乏描述性
  • 缺少跳过链接
  • 媒体自动播放

中等(尽快修复):

  • 图标缺少 ARIA 标签
  • 导航不一致
  • 缺少错误识别
  • 缺少地标区域
阶段 4:手动测试

按照 references/screen-reader-guide.md 进行:

  • 键盘导航测试
  • 屏幕阅读器测试(VoiceOver、NVDA、JAWS)
  • 缩放和重排测试
  • 高对比度模式测试
  • 减少动态效果测试

WCAG 模式示例

可感知
替代文本(1.1.1)

<img src="chart.png">


<img src="chart.png" alt="Bar chart showing 40% increase in Q3 sales">


<img src="decorative-border.png" alt="" role="presentation">
颜色对比度(1.4.3)
/* ❌ Low contrast (2.5:1) */
.low-contrast {
  color: #999;
  background: #fff;
}

/* ✅ Sufficient contrast (7:1) */
.high-contrast {
  color: #333;
  background: #fff;
}

对比度要求:

  • 普通文本:4.5:1(AA)、7:1(AAA)
  • 大号文本(18px+ 或 14px+ 粗体):3:1(AA)、4.5:1(AAA)
  • UI 组件:3:1
媒体替代方案(1.2)
<video controls>
  <source src="video.mp4" type="video/mp4">
  <track kind="captions" src="captions.vtt" srclang="en" label="English" default>
</video>
可操作
键盘导航(2.1.1)
// ❌ Only click
element.addEventListener('click', handleAction);

// ✅ Click + keyboard
element.addEventListener('click', handleAction);
element.addEventListener('keydown', (e) => {
  if (e.key === 'Enter' || e.key === ' ') {
    e.preventDefault();
    handleAction();
  }
});
焦点可见(2.4.7)
/* ❌ Never remove focus */
*:focus { outline: none; }

/* ✅ Keyboard-only focus */
:focus-visible {
  outline: 2px solid #005fcc;
  outline-offset: 2px;
}
跳过链接(2.4.1)
<body>
  <a href="#main-content" class="skip-link">Skip to main content</a>
  <header></header>
  <main id="main-content" tabindex="-1">
    
  </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;
}
减少动态效果(2.3.3)
@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;
  }
}
易于理解
页面语言(3.1.1)

<html>


<html lang="en">


<p>The French word for hello is <span lang="fr">bonjour</span>.</p>
表单标签(3.3.2)

<input type="email" placeholder="Email">


<label for="email">Email address</label>
<input type="email" id="email" autocomplete="email">


<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>
错误处理(3.3.1)
<label for="email">Email</label>
<input type="email" id="email" 
       aria-invalid="true" 
       aria-describedby="email-error">
<p id="email-error" role="alert">
  Please enter a valid email address.
</p>
健壮
ARIA 用法(4.1.2)

<button role="button">Submit</button>


<button>Submit</button>


<div role="tablist" aria-label="Product information">
  <button role="tab" aria-selected="true" aria-controls="panel-1">
    Description
  </button>
  <button role="tab" aria-selected="false" aria-controls="panel-2" tabindex="-1">
    Reviews
  </button>
</div>
<div role="tabpanel" id="panel-1" aria-labelledby="tab-1">
  
</div>
实时区域(4.1.3)

<div aria-live="polite" aria-atomic="true">
  Status update
</div>


<div role="alert" aria-live="assertive">
  Error: Form submission failed
</div>
视觉隐藏文本
.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;
}
<button>
  <svg aria-hidden="true"></svg>
  <span class="visually-hidden">Delete item</span>
</button>

输出格式

生成结构如下的报告:

# Accessibility Audit Report

## Summary
- Total Issues: X
- Critical: X | Serious: X | Moderate: X | Minor: X
- WCAG Level: A, AA, or AAA
- Automated Coverage: ~57% (manual testing required)

## Critical Issues (Fix Immediately)

### 1. [Issue Name] - WCAG X.X.X
**Severity:** Critical  
**Impact:** [Who is affected and how]  
**Affected:** X elements

**Locations:**
- `path/to/file.tsx:123`
- `path/to/file.tsx:456`

**Problem:**
[Brief description]

**Fix:**
```tsx
// Before
<div onClick={handleClick}>Click me</div>

// After
<button onClick={handleClick}>Click me</button>

原因:[无障碍原则]


较严重的问题

[相同格式]

中等问题

[相同格式]

测试建议

  1. 手动键盘测试(Tab、Enter、Escape)
  2. 屏幕阅读器测试(参见 references/screen-reader-guide.md)
  3. 自动化测试设置(@axe-core/react 或 Lighthouse CI)
  4. 颜色对比度验证(WebAIM Contrast Checker)

后续步骤

[按优先级排列的行动项]


---

## Tools & Resources

### Development Tools
- **eslint-plugin-jsx-a11y** - React/JSX static analysis (~37 rules)
- **axe-core DevTools** - Browser extension for runtime testing
- **Lighthouse** - Built into Chrome DevTools

### Testing Tools  
- **@axe-core/react** - Runtime accessibility testing
- **@axe-core/playwright** - E2E test integration
- **pa11y** - Automated command-line testing

### Manual Testing
- **WebAIM Contrast Checker** - https://webaim.org/resources/contrastchecker/
- **WAVE** - Browser extension for visual feedback
- **Screen readers** - NVDA (Windows), VoiceOver (macOS), JAWS

### Reference Docs
- `references/WCAG-criteria.md` - All WCAG 2.1 success criteria
- `references/ARIA-patterns.md` - Common ARIA patterns and examples
- `references/screen-reader-guide.md` - Testing commands and scenarios
- `references/grep-patterns.md` - Search patterns for code audits

### References
- [WebAIM Million](https://webaim.org/projects/million/) - Annual analysis of top 1M websites (violation statistics)
- [WCAG 2.1 Quick Reference](https://www.w3.org/WAI/WCAG21/quickref/) - Interactive WCAG guide
- [WAI-ARIA Authoring Practices](https://www.w3.org/WAI/ARIA/apg/) - Official ARIA patterns
- [Deque axe Rules](https://dequeuniversity.com/rules/axe/) - All axe-core rules explained
- [jsx-a11y Rules](https://github.com/jsx-eslint/eslint-plugin-jsx-a11y#supported-rules) - ESLint accessibility rules

---

## Important Notes

- Automated tools catch 30-57% of issues; manual testing required
- Pages with ARIA average 41% more errors than without
- Always test with actual assistive technology when possible
- Focus on critical issues first (keyboard, screen readers, contrast)
- Document deliberate accessibility decisions
- Test on multiple browsers and devices
- Include users with disabilities in testing when possible

## Common Pitfalls to Avoid

1. Relying solely on automated testing
2. Using ARIA when native HTML suffices
3. Removing focus indicators
4. Using positive tabindex values
5. Color as only means of conveying information
6. Keyboard traps in modals/dialogs
7. Non-descriptive link text
8. Missing or incorrect heading hierarchy
9. Unlabeled form controls
10. Missing language attributes

评论

支持 Markdown