wcag-audit-patterns

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

WCAG Audit Patterns

WCAG审计模式

Comprehensive guide to auditing web content against WCAG 2.2 guidelines with actionable remediation strategies.
针对WCAG 2.2指南的网页内容综合审计指南,附可行的修复策略。

When to Use This Skill

何时使用此技能

  • Conducting accessibility audits
  • Fixing WCAG violations
  • Implementing accessible components
  • Preparing for accessibility lawsuits
  • Meeting ADA/Section 508 requirements
  • Achieving VPAT compliance
  • 开展无障碍审计
  • 修复WCAG违规问题
  • 实现无障碍组件
  • 为无障碍诉讼做准备
  • 满足ADA/Section 508要求
  • 达成VPAT合规

Core Concepts

核心概念

1. WCAG Conformance Levels

1. WCAG合规等级

LevelDescriptionRequired For
AMinimum accessibilityLegal baseline
AAStandard conformanceMost regulations
AAAEnhanced accessibilitySpecialized needs
等级描述适用场景
A最低无障碍要求法律基线
AA标准合规大多数法规要求
AAA增强型无障碍特殊需求场景

2. POUR Principles

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?
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. Common Violations by Impact

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

Audit Checklist

审计检查清单

Perceivable (Principle 1)

可感知性(原则1)

markdown
undefined
markdown
undefined

1.1 Text Alternatives

1.1 文本替代方案

1.1.1 Non-text Content (Level A)

1.1.1 非文本内容(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
<!-- Good -->
<img src="chart.png" alt="Sales increased 25% from Q1 to Q2" />
<img src="decorative-line.png" alt="" />

<!-- Bad -->
<img src="chart.png" />
<img src="decorative-line.png" alt="decorative line" />
undefined
  • 所有图片均有替代文本(alt text)
  • 装饰性图片使用alt=""
  • 复杂图片配有详细描述
  • 具有含义的图标配有可访问名称
  • CAPTCHA提供替代方案
检查示例:
html
<!-- Good -->
<img src="chart.png" alt="Sales increased 25% from Q1 to Q2" />
<img src="decorative-line.png" alt="" />

<!-- Bad -->
<img src="chart.png" />
<img src="decorative-line.png" alt="decorative line" />
undefined

1.2 Time-based Media

1.2 基于时间的媒体

1.2.1 Audio-only and Video-only (Level A)

1.2.1 仅音频和仅视频内容(A级)

  • Audio has text transcript
  • Video has audio description or transcript
  • 音频配有文字转录稿
  • 视频配有音频描述或转录稿

1.2.2 Captions (Level A)

1.2.2 字幕(A级)

  • All video has synchronized captions
  • Captions are accurate and complete
  • Speaker identification included
  • 所有视频配有同步字幕
  • 字幕准确完整
  • 包含说话人标识

1.2.3 Audio Description (Level A)

1.2.3 音频描述(A级)

  • Video has audio description for visual content
  • 视频为视觉内容提供音频描述

1.3 Adaptable

1.3 可适应性

1.3.1 Info and Relationships (Level A)

1.3.1 信息与关系(A级)

  • Headings use proper tags (h1-h6)
  • Lists use ul/ol/dl
  • Tables have headers
  • Form inputs have labels
  • ARIA landmarks present
Check:
html
<!-- Heading hierarchy -->
<h1>Page Title</h1>
<h2>Section</h2>
<h3>Subsection</h3>
<h2>Another Section</h2>

<!-- Table headers -->
<table>
  <thead>
    <tr>
      <th scope="col">Name</th>
      <th scope="col">Price</th>
    </tr>
  </thead>
</table>
  • 标题使用正确的标签(h1-h6)
  • 列表使用ul/ol/dl标签
  • 表格配有表头
  • 表单输入项配有标签
  • 存在ARIA地标
检查示例:
html
<!-- Heading hierarchy -->
<h1>Page Title</h1>
<h2>Section</h2>
<h3>Subsection</h3>
<h2>Another Section</h2>

<!-- Table headers -->
<table>
  <thead>
    <tr>
      <th scope="col">Name</th>
      <th scope="col">Price</th>
    </tr>
  </thead>
</table>

1.3.2 Meaningful Sequence (Level A)

1.3.2 有意义的顺序(A级)

  • Reading order is logical
  • CSS positioning doesn't break order
  • Focus order matches visual order
  • 阅读顺序符合逻辑
  • CSS定位不破坏顺序
  • 焦点顺序与视觉顺序一致

1.3.3 Sensory Characteristics (Level A)

1.3.3 感官特性(A级)

  • Instructions don't rely on shape/color alone
  • "Click the red button" → "Click Submit (red button)"
  • 操作说明不单独依赖形状/颜色
  • 避免“点击红色按钮”,改为“点击提交(红色按钮)”

1.4 Distinguishable

1.4 可区分性

1.4.1 Use of Color (Level A)

1.4.1 颜色的使用(A级)

  • Color is not only means of conveying info
  • Links distinguishable without color
  • Error states not color-only
  • 不单独使用颜色传递信息
  • 链接无需依赖颜色即可区分
  • 错误状态不单独通过颜色标识

1.4.3 Contrast (Minimum) (Level AA)

1.4.3 对比度(最低要求)(AA级)

  • Text: 4.5:1 contrast ratio
  • Large text (18pt+): 3:1 ratio
  • UI components: 3:1 ratio
Tools: WebAIM Contrast Checker, axe DevTools
  • 文本对比度达到4.5:1
  • 大文本(18pt及以上)对比度达到3:1
  • UI组件对比度达到3:1
工具:WebAIM对比度检查器、axe DevTools

1.4.4 Resize Text (Level AA)

1.4.4 文本缩放(AA级)

  • Text resizes to 200% without loss
  • No horizontal scrolling at 320px
  • Content reflows properly
  • 文本可缩放至200%且无内容丢失
  • 在320px宽度下无水平滚动
  • 内容可正确重排

1.4.10 Reflow (Level AA)

1.4.10 重排(AA级)

  • Content reflows at 400% zoom
  • No two-dimensional scrolling
  • All content accessible at 320px width
  • 内容在400%缩放时可重排
  • 无二维滚动
  • 在320px宽度下所有内容均可访问

1.4.11 Non-text Contrast (Level AA)

1.4.11 非文本对比度(AA级)

  • UI components have 3:1 contrast
  • Focus indicators visible
  • Graphical objects distinguishable
  • UI组件对比度达到3:1
  • 焦点指示器可见
  • 图形对象可区分

1.4.12 Text Spacing (Level AA)

1.4.12 文本间距(AA级)

  • No content loss with increased spacing
  • Line height 1.5x font size
  • Paragraph spacing 2x font size
  • Letter spacing 0.12x font size
  • Word spacing 0.16x font size
undefined
  • 增加间距后无内容丢失
  • 行高为字体大小的1.5倍
  • 段落间距为字体大小的2倍
  • 字母间距为字体大小的0.12倍
  • 单词间距为字体大小的0.16倍
undefined

Operable (Principle 2)

可操作性(原则2)

markdown
undefined
markdown
undefined

2.1 Keyboard Accessible

2.1 键盘可访问性

2.1.1 Keyboard (Level A)

2.1.1 键盘操作(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()">
  • 所有功能均可通过键盘访问
  • 无键盘陷阱
  • Tab键顺序符合逻辑
  • 自定义组件可通过键盘操作
检查示例:
javascript
// Custom button must be keyboard accessible
<div role="button" tabindex="0"
     onkeydown="if(event.key === 'Enter' || event.key === ' ') activate()">

2.1.2 No Keyboard Trap (Level A)

2.1.2 无键盘陷阱(A级)

  • Focus can move away from all components
  • Modal dialogs trap focus correctly
  • Focus returns after modal closes
  • 焦点可从所有组件移出
  • 模态对话框正确捕获焦点
  • 模态框关闭后焦点返回原位置

2.2 Enough Time

2.2 充足的时间

2.2.1 Timing Adjustable (Level A)

2.2.1 可调整计时(A级)

  • Session timeouts can be extended
  • User warned before timeout
  • Option to disable auto-refresh
  • 会话超时可延长
  • 超时前向用户发出警告
  • 可禁用自动刷新

2.2.2 Pause, Stop, Hide (Level A)

2.2.2 暂停、停止、隐藏(A级)

  • Moving content can be paused
  • Auto-updating content can be paused
  • Animations respect prefers-reduced-motion
css
@media (prefers-reduced-motion: reduce) {
  * {
    animation: none !important;
    transition: none !important;
  }
}
  • 动态内容可暂停
  • 自动更新内容可暂停
  • 动画尊重prefers-reduced-motion设置
css
@media (prefers-reduced-motion: reduce) {
  * {
    animation: none !important;
    transition: none !important;
  }
}

2.3 Seizures and Physical Reactions

2.3 癫痫发作和身体反应

2.3.1 Three Flashes (Level A)

2.3.1 三次闪烁(A级)

  • No content flashes more than 3 times/second
  • Flashing area is small (<25% viewport)
  • 内容闪烁频率不超过每秒3次
  • 闪烁区域小于视口的25%

2.4 Navigable

2.4 可导航性

2.4.1 Bypass Blocks (Level A)

2.4.1 绕过重复区块(A级)

  • Skip to main content link present
  • Landmark regions defined
  • Proper heading structure
html
<a href="#main" class="skip-link">Skip to main content</a>
<main id="main">...</main>
  • 存在“跳转到主要内容”链接
  • 定义了地标区域
  • 标题结构合理
html
<a href="#main" class="skip-link">Skip to main content</a>
<main id="main">...</main>

2.4.2 Page Titled (Level A)

2.4.2 页面标题(A级)

  • Unique, descriptive page titles
  • Title reflects page content
  • 页面标题唯一且具有描述性
  • 标题反映页面内容

2.4.3 Focus Order (Level A)

2.4.3 焦点顺序(A级)

  • Focus order matches visual order
  • tabindex used correctly
  • 焦点顺序与视觉顺序一致
  • 正确使用tabindex

2.4.4 Link Purpose (In Context) (Level A)

2.4.4 链接用途(上下文内)(A级)

  • Links make sense out of context
  • No "click here" or "read more" alone
html
<!-- Bad -->
<a href="report.pdf">Click here</a>

<!-- Good -->
<a href="report.pdf">Download Q4 Sales Report (PDF)</a>
  • 链接脱离上下文仍有明确含义
  • 避免单独使用“点击这里”或“阅读更多”
html
<!-- Bad -->
<a href="report.pdf">Click here</a>

<!-- Good -->
<a href="report.pdf">Download Q4 Sales Report (PDF)</a>

2.4.6 Headings and Labels (Level AA)

2.4.6 标题与标签(AA级)

  • Headings describe content
  • Labels describe purpose
  • 标题准确描述内容
  • 标签准确说明用途

2.4.7 Focus Visible (Level AA)

2.4.7 可见焦点(AA级)

  • Focus indicator visible on all elements
  • Custom focus styles meet contrast
css
:focus {
  outline: 3px solid #005fcc;
  outline-offset: 2px;
}
  • 所有元素的焦点指示器可见
  • 自定义焦点样式符合对比度要求
css
:focus {
  outline: 3px solid #005fcc;
  outline-offset: 2px;
}

2.4.11 Focus Not Obscured (Level AA) - WCAG 2.2

2.4.11 焦点不被遮挡(AA级)- WCAG 2.2

  • Focused element not fully hidden
  • Sticky headers don't obscure focus
undefined
  • 获得焦点的元素不会被完全遮挡
  • 粘性页眉不会遮挡焦点
undefined

Understandable (Principle 3)

可理解性(原则3)

markdown
undefined
markdown
undefined

3.1 Readable

3.1 可读性

3.1.1 Language of Page (Level A)

3.1.1 页面语言(A级)

  • HTML lang attribute set
  • Language correct for content
html
<html lang="en">
  • 设置了HTML lang属性
  • 语言与内容匹配
html
<html lang="en">

3.1.2 Language of Parts (Level AA)

3.1.2 局部内容语言(AA级)

  • Language changes marked
html
<p>The French word <span lang="fr">bonjour</span> means hello.</p>
  • 语言变化处有标识
html
<p>The French word <span lang="fr">bonjour</span> means hello.</p>

3.2 Predictable

3.2 可预测性

3.2.1 On Focus (Level A)

3.2.1 聚焦时(A级)

  • No context change on focus alone
  • No unexpected popups on focus
  • 仅聚焦操作不会导致上下文变化
  • 聚焦时不会弹出意外窗口

3.2.2 On Input (Level A)

3.2.2 输入时(A级)

  • No automatic form submission
  • User warned before context change
  • 无自动表单提交
  • 上下文变化前向用户发出警告

3.2.3 Consistent Navigation (Level AA)

3.2.3 导航一致性(AA级)

  • Navigation consistent across pages
  • Repeated components same order
  • 导航在所有页面保持一致
  • 重复组件顺序相同

3.2.4 Consistent Identification (Level AA)

3.2.4 标识一致性(AA级)

  • Same functionality = same label
  • Icons used consistently
  • 相同功能使用相同标签
  • 图标使用保持一致

3.3 Input Assistance

3.3 输入辅助

3.3.1 Error Identification (Level A)

3.3.1 错误识别(A级)

  • Errors clearly identified
  • Error message describes problem
  • Error linked to field
html
<input aria-describedby="email-error" aria-invalid="true" />
<span id="email-error" role="alert">Please enter valid email</span>
  • 错误被清晰标识
  • 错误消息描述问题
  • 错误与对应字段关联
html
<input aria-describedby="email-error" aria-invalid="true" />
<span id="email-error" role="alert">Please enter valid email</span>

3.3.2 Labels or Instructions (Level A)

3.3.2 标签或说明(A级)

  • All inputs have visible labels
  • Required fields indicated
  • Format hints provided
  • 所有输入项均有可见标签
  • 必填字段有明确标识
  • 提供格式提示

3.3.3 Error Suggestion (Level AA)

3.3.3 错误建议(AA级)

  • Errors include correction suggestion
  • Suggestions are specific
  • 错误提示包含修正建议
  • 建议具体明确

3.3.4 Error Prevention (Level AA)

3.3.4 错误预防(AA级)

  • Legal/financial forms reversible
  • Data checked before submission
  • User can review before submit
undefined
  • 法律/金融表单可撤销
  • 提交前检查数据
  • 用户可在提交前复查内容
undefined

Robust (Principle 4)

健壮性(原则4)

markdown
undefined
markdown
undefined

4.1 Compatible

4.1 兼容性

4.1.1 Parsing (Level A) - Obsolete in WCAG 2.2

4.1.1 解析(A级)- WCAG 2.2中已废弃

  • Valid HTML (good practice)
  • No duplicate IDs
  • Complete start/end tags
  • 使用有效的HTML(最佳实践)
  • 无重复ID
  • 标签完整闭合

4.1.2 Name, Role, Value (Level A)

4.1.2 名称、角色、值(A级)

  • Custom widgets have accessible names
  • ARIA roles correct
  • State changes announced
html
<!-- Accessible custom checkbox -->
<div role="checkbox"
     aria-checked="false"
     tabindex="0"
     aria-labelledby="label">
</div>
<span id="label">Accept terms</span>
  • 自定义组件具有可访问名称
  • ARIA角色正确
  • 状态变化可被辅助技术识别
html
<!-- Accessible custom checkbox -->
<div role="checkbox"
     aria-checked="false"
     tabindex="0"
     aria-labelledby="label">
</div>
<span id="label">Accept terms</span>

4.1.3 Status Messages (Level AA)

4.1.3 状态消息(AA级)

  • Status updates announced
  • Live regions used correctly
html
<div role="status" aria-live="polite">3 items added to cart</div>

<div role="alert" aria-live="assertive">Error: Form submission failed</div>
undefined
  • 状态更新可被辅助技术播报
  • 正确使用实时区域(live regions)
html
<div role="status" aria-live="polite">3 items added to cart</div>

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

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);
});
bash
undefined
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);
});
bash
undefined

CLI tools

CLI tools

npx @axe-core/cli https://example.com npx pa11y https://example.com lighthouse https://example.com --only-categories=accessibility
undefined
npx @axe-core/cli https://example.com npx pa11y https://example.com lighthouse https://example.com --only-categories=accessibility
undefined

Remediation Patterns

修复模式

Fix: Missing Form Labels

修复方案:缺失表单标签

html
<!-- Before -->
<input type="email" placeholder="Email" />

<!-- After: Option 1 - Visible label -->
<label for="email">Email address</label>
<input id="email" type="email" />

<!-- After: Option 2 - aria-label -->
<input type="email" aria-label="Email address" />

<!-- After: Option 3 - aria-labelledby -->
<span id="email-label">Email</span>
<input type="email" aria-labelledby="email-label" />
html
<!-- Before -->
<input type="email" placeholder="Email" />

<!-- After: Option 1 - Visible label -->
<label for="email">Email address</label>
<input id="email" type="email" />

<!-- After: Option 2 - aria-label -->
<input type="email" aria-label="Email address" />

<!-- After: Option 3 - aria-labelledby -->
<span id="email-label">Email</span>
<input type="email" aria-labelledby="email-label" />

Fix: Insufficient Color Contrast

修复方案:颜色对比度不足

css
/* Before: 2.5:1 contrast */
.text {
  color: #767676;
}

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

/* Or add background */
.text {
  color: #767676;
  background: #000;
}
css
/* Before: 2.5:1 contrast */
.text {
  color: #767676;
}

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

/* Or add background */
.text {
  color: #767676;
  background: #000;
}

Fix: Keyboard Navigation

修复方案:键盘导航

javascript
// 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;
      }
    });
  }
}
javascript
// 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;
      }
    });
  }
}

Best Practices

最佳实践

Do's

建议事项

  • Start early - Accessibility from design phase
  • Test with real users - Disabled users provide best feedback
  • Automate what you can - 30-50% issues detectable
  • Use semantic HTML - Reduces ARIA needs
  • Document patterns - Build accessible component library
  • 尽早开始 - 从设计阶段就考虑无障碍
  • 与真实用户测试 - 残障用户的反馈最有价值
  • 尽可能自动化 - 30-50%的问题可通过自动化检测
  • 使用语义化HTML - 减少对ARIA的依赖
  • 记录模式 - 构建无障碍组件库

Don'ts

避免事项

  • Don't rely only on automated testing - Manual testing required
  • Don't use ARIA as first solution - Native HTML first
  • Don't hide focus outlines - Keyboard users need them
  • Don't disable zoom - Users need to resize
  • Don't use color alone - Multiple indicators needed
  • 不要仅依赖自动化测试 - 必须配合人工测试
  • 不要优先使用ARIA - 优先使用原生HTML
  • 不要隐藏焦点轮廓 - 键盘用户需要它们
  • 不要禁用缩放 - 用户需要调整大小
  • 不要单独使用颜色 - 需搭配其他标识

Resources

参考资源