mcpField
W
wcag-audit-patterns

wcag-audit-patterns

github.com/marcioaltoe测试与质量046 次安装1 天前更新
代码仓库

关于 wcag-audit-patterns

一项依据 WCAG 2.2 审查网页内容并规划整改的参考技能,面向开发者和无障碍审查人员,提供检查清单、代码示例及自动化测试指引。

主要功能

  1. 01WCAG 符合等级与 POUR 原则
  2. 02覆盖无障碍标准的审查清单
  3. 03常见问题及整改模式
  4. 04axe-core 与 Playwright 测试示例
  5. 05无障碍测试命令行示例

适用场景

  1. 01检查网站的 WCAG 问题
  2. 02规划表单标签和键盘访问整改
  3. 03在 Playwright 测试中加入无障碍检查

安装

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

$npx skills add https://github.com/marcioaltoe/skills --skill wcag-audit-patterns

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

附带文件agents/openai.yaml

详细介绍

WCAG 审计模式

全面介绍如何依据 WCAG 2.2 指南审计网页内容,并提供可执行的修复策略。

何时使用此技能

  • 开展无障碍审计
  • 修复 WCAG 违规问题
  • 实现无障碍组件
  • 为无障碍诉讼做准备
  • 满足 ADA/Section 508 要求
  • 达到 VPAT 合规要求

核心概念

1. WCAG 合规等级
等级描述适用要求
A最低无障碍要求法律基线
AA标准合规大多数法规
AAA增强型无障碍要求特殊需求
2. POUR 原则
Perceivable:  Can users perceive the content?
Operable:     Can users operate the interface?
Understandable: Can users understand the content?
Robust:       Does it work with assistive tech?
3. 按影响程度划分的常见违规问题
Critical (Blockers):
├── Missing alt text for functional images
├── No keyboard access to interactive elements
├── Missing form labels
└── Auto-playing media without controls

Serious:
├── Insufficient color contrast
├── Missing skip links
├── Inaccessible custom widgets
└── Missing page titles

Moderate:
├── Missing language attribute
├── Unclear link text
├── Missing landmarks
└── Improper heading hierarchy

审计清单

可感知性(原则 1)
## 1.1 Text Alternatives

### 1.1.1 Non-text Content (Level A)

- [ ] All images have alt text
- [ ] Decorative images have alt=""
- [ ] Complex images have long descriptions
- [ ] Icons with meaning have accessible names
- [ ] CAPTCHAs have alternatives

Check:

```html

<img src="chart.png" alt="Sales increased 25% from Q1 to Q2" />
<img src="decorative-line.png" alt="" />


<img src="chart.png" />
<img src="decorative-line.png" alt="decorative line" />
```

1.2 基于时间的媒体

1.2.1 纯音频和纯视频(A级)
  • 音频提供文本转录稿
  • 视频提供音频描述或转录稿
1.2.2 字幕(A级)
  • 所有视频都提供同步字幕
  • 字幕准确且完整
  • 包含说话人标识
1.2.3 音频描述(A级)
  • 视频为视觉内容提供音频描述

1.3 适应性

1.3.1 信息和关系(A级)
  • 标题使用正确的标签(h1-h6)
  • 列表使用 ul/ol/dl
  • 表格包含表头
  • 表单输入项带有标签
  • 存在 ARIA 地标

检查:


<h1>Page Title</h1>
<h2>Section</h2>
<h3>Subsection</h3>
<h2>Another Section</h2>


<table>
  <thead>
    <tr>
      <th scope="col">Name</th>
      <th scope="col">Price</th>
    </tr>
  </thead>
</table>
1.3.2 有意义的顺序(A级)
  • 阅读顺序符合逻辑
  • CSS 定位不会打乱顺序
  • 焦点顺序与视觉顺序一致
1.3.3 感官特征(A级)
  • 说明不单独依赖形状或颜色
  • “点击红色按钮” → “点击提交(红色按钮)”

1.4 可辨识性

1.4.1 颜色的使用(A级)
  • 不单独依靠颜色传达信息
  • 链接无需借助颜色也能辨识
  • 错误状态不只通过颜色表示
1.4.3 对比度(最低)(AA级)
  • 文本:对比度至少为 4.5:1
  • 大号文本(18pt 以上):对比度至少为 3:1
  • UI 组件:对比度至少为 3:1

工具:WebAIM Contrast Checker、axe DevTools

1.4.4 调整文本大小(AA级)
  • 文本可放大至 200%,且内容不丢失
  • 在 320px 宽度下无需水平滚动
  • 内容可正常重排
1.4.10 重排(AA级)
  • 内容在 400% 缩放下可重排
  • 无需二维滚动
  • 在 320px 宽度下可访问所有内容
1.4.11 非文本对比度(AA级)
  • UI 组件的对比度至少为 3:1
  • 焦点指示器清晰可见
  • 图形对象易于辨识
1.4.12 文本间距(AA级)
  • 增大间距后内容不会丢失
  • 行高为字体大小的 1.5 倍
  • 段落间距为字体大小的 2 倍
  • 字符间距为字体大小的 0.12 倍
  • 单词间距为字体大小的 0.16 倍

### Operable (Principle 2)

```markdown
## 2.1 Keyboard Accessible

### 2.1.1 Keyboard (Level A)
- [ ] All functionality keyboard accessible
- [ ] No keyboard traps
- [ ] Tab order is logical
- [ ] Custom widgets are keyboard operable

Check:
```javascript
// Custom button must be keyboard accessible
<div role="button" tabindex="0"
     onkeydown="if(event.key === 'Enter' || event.key === ' ') activate()">
2.1.2 无键盘陷阱(A级)
  • 焦点可移出所有组件
  • 模态对话框可正确锁定焦点
  • 模态对话框关闭后焦点返回

2.2 时间充足

2.2.1 可调整计时(A级)
  • 可延长会话超时时间
  • 超时前向用户发出警告
  • 可禁用自动刷新
2.2.2 暂停、停止、隐藏(A级)
  • 可暂停移动内容
  • 可暂停自动更新的内容
  • 动画遵循 prefers-reduced-motion 设置
@media (prefers-reduced-motion: reduce) {
  * {
    animation: none !important;
    transition: none !important;
  }
}

2.3 癫痫发作和生理反应

2.3.1 三次闪烁(A级)
  • 内容每秒闪烁不超过 3 次
  • 闪烁区域较小(小于视口的 25%)

2.4 可导航性

2.4.1 跳过区块(A级)
  • 提供“跳转到主要内容”链接
  • 定义地标区域
  • 标题结构正确
<a href="#main" class="skip-link">Skip to main content</a>
<main id="main">...</main>
2.4.2 页面标题(A级)
  • 页面标题唯一且具有描述性
  • 标题反映页面内容
2.4.3 焦点顺序(A级)
  • 焦点顺序与视觉顺序一致
  • 正确使用 tabindex
2.4.4 链接用途(结合上下文)(A 级)
  • 链接脱离上下文后仍有明确含义
  • 不单独使用“点击此处”或“阅读更多”

<a href="report.pdf">Click here</a>


<a href="report.pdf">Download Q4 Sales Report (PDF)</a>
2.4.6 标题和标签(AA 级)
  • 标题能描述内容
  • 标签能描述用途
2.4.7 焦点可见(AA 级)
  • 所有元素上的焦点指示器都清晰可见
  • 自定义焦点样式符合对比度要求
:focus {
  outline: 3px solid #005fcc;
  outline-offset: 2px;
}
2.4.11 焦点未被遮挡(AA 级)- WCAG 2.2
  • 获得焦点的元素未被完全隐藏
  • 粘性页眉不会遮挡焦点

### Understandable (Principle 3)

```markdown
## 3.1 Readable

### 3.1.1 Language of Page (Level A)
- [ ] HTML lang attribute set
- [ ] Language correct for content

```html
<html lang="en">
3.1.2 部分内容的语言(AA 级)
  • 标记语言变更
<p>The French word <span lang="fr">bonjour</span> means hello.</p>

3.2 可预测

3.2.1 获得焦点时(A 级)
  • 仅获得焦点不会导致上下文变化
  • 获得焦点时不会出现意外弹窗
3.2.2 输入时(A 级)
  • 不自动提交表单
  • 上下文变化前向用户发出提示
3.2.3 一致的导航(AA 级)
  • 各页面的导航保持一致
  • 重复组件的顺序相同
3.2.4 一致的标识(AA 级)
  • 相同功能使用相同标签
  • 图标的使用保持一致

3.3 输入辅助

3.3.1 错误识别(A 级)
  • 清晰标识错误
  • 错误消息描述问题
  • 错误与对应字段关联
<input aria-describedby="email-error" aria-invalid="true" />
<span id="email-error" role="alert">Please enter valid email</span>
3.3.2 标签或说明(A 级)
  • 所有输入项都有可见标签
  • 标明必填字段
  • 提供格式提示
3.3.3 错误建议(AA 级)
  • 错误信息包含更正建议
  • 建议具体明确
3.3.4 错误预防(AA 级)
  • 法律或财务表单可撤销
  • 提交前检查数据
  • 用户可以在提交前进行审核

### Robust (Principle 4)

```markdown
## 4.1 Compatible

### 4.1.1 Parsing (Level A) - Obsolete in WCAG 2.2
- [ ] Valid HTML (good practice)
- [ ] No duplicate IDs
- [ ] Complete start/end tags

### 4.1.2 Name, Role, Value (Level A)
- [ ] Custom widgets have accessible names
- [ ] ARIA roles correct
- [ ] State changes announced

```html

<div role="checkbox"
     aria-checked="false"
     tabindex="0"
     aria-labelledby="label">
</div>
<span id="label">Accept terms</span>
4.1.3 状态消息(AA 级)
  • 播报状态更新
  • 正确使用实时区域
<div role="status" aria-live="polite">3 items added to cart</div>

<div role="alert" aria-live="assertive">Error: Form submission failed</div>

## Automated Testing

```javascript
// axe-core integration
const axe = require('axe-core');

async function runAccessibilityAudit(page) {
  await page.addScriptTag({ path: require.resolve('axe-core') });

  const results = await page.evaluate(async () => {
    return await axe.run(document, {
      runOnly: {
        type: 'tag',
        values: ['wcag2a', 'wcag2aa', 'wcag21aa', 'wcag22aa']
      }
    });
  });

  return {
    violations: results.violations,
    passes: results.passes,
    incomplete: results.incomplete
  };
}

// Playwright test example
test('should have no accessibility violations', async ({ page }) => {
  await page.goto('/');
  const results = await runAccessibilityAudit(page);

  expect(results.violations).toHaveLength(0);
});
# CLI tools
npx @axe-core/cli https://example.com
npx pa11y https://example.com
lighthouse https://example.com --only-categories=accessibility

修复模式

修复:缺少表单标签

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


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


<input type="email" aria-label="Email address" />


<span id="email-label">Email</span>
<input type="email" aria-labelledby="email-label" />
修复:颜色对比度不足
/* Before: 2.5:1 contrast */
.text {
  color: #767676;
}

/* After: 4.5:1 contrast */
.text {
  color: #595959;
}

/* Or add background */
.text {
  color: #767676;
  background: #000;
}
修复:键盘导航
// Make custom element keyboard accessible
class AccessibleDropdown extends HTMLElement {
  connectedCallback() {
    this.setAttribute("tabindex", "0");
    this.setAttribute("role", "combobox");
    this.setAttribute("aria-expanded", "false");

    this.addEventListener("keydown", (e) => {
      switch (e.key) {
        case "Enter":
        case " ":
          this.toggle();
          e.preventDefault();
          break;
        case "Escape":
          this.close();
          break;
        case "ArrowDown":
          this.focusNext();
          e.preventDefault();
          break;
        case "ArrowUp":
          this.focusPrevious();
          e.preventDefault();
          break;
      }
    });
  }
}

最佳实践

应该做
  • 尽早开始 - 从设计阶段开始考虑无障碍性
  • 使用真实用户进行测试 - 残障用户能提供最佳反馈
  • 尽可能自动化 - 可检测出 30-50% 的问题
  • 使用语义化 HTML - 减少对 ARIA 的需求
  • 记录模式 - 构建无障碍组件库
不应该做
  • 不要只依赖自动化测试 - 还需要手动测试
  • 不要首先使用 ARIA 解决问题 - 优先使用原生 HTML
  • 不要隐藏焦点轮廓 - 键盘用户需要它们
  • 不要禁用缩放 - 用户需要调整大小
  • 不要只使用颜色 - 需要多种指示方式

评论

支持 Markdown