wcag-design
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseWCAG-Design Skill
WCAG-Design 技能
This skill guides the creation of accessible, visually distinctive frontend interfaces that conform
to WCAG 2.2 AA standards. Accessibility and design quality are not opposing forces — the best
accessible interfaces are also beautifully designed.
该技能指导开发者构建符合WCAG 2.2 AA标准的可访问、视觉辨识度高的前端界面。无障碍性和设计质量并非对立关系——最优秀的无障碍界面同时也具备出色的设计效果。
Part 1 — WCAG Fundamentals
第1部分 — WCAG基础
What is WCAG?
什么是WCAG?
The Web Content Accessibility Guidelines (WCAG) is the global standard for web accessibility,
published by the W3C through the Web Accessibility Initiative (WAI). WCAG defines how to make web
content accessible to people with disabilities including blindness, low vision, deafness, hearing
loss, limited movement, photosensitivity, speech disabilities, and cognitive/learning disabilities.
**Web内容无障碍指南(Web Content Accessibility Guidelines, WCAG)**是W3C通过Web无障碍倡议(Web Accessibility Initiative, WAI)发布的全球Web无障碍标准。WCAG定义了如何让Web内容对各类残障人士可访问,包括失明、低视力、耳聋、听力损失、行动受限、光敏性癫痫、言语障碍、认知/学习障碍人群。
Version History
版本历史
| Version | Year | Notes |
|---|---|---|
| WCAG 1.0 | 1999 | First W3C accessibility recommendation |
| WCAG 2.0 | 2008 | Major restructure with testable success criteria |
| WCAG 2.1 | 2018 | +17 new criteria for mobile, low vision, cognitive |
| WCAG 2.2 | 2023 | +9 new criteria, removed 4.1.1 Parsing; current standard |
| WCAG 3.0 | ~2028 | Draft; plain language, outcome-oriented model |
Backward compatibility: Content conforming to WCAG 2.2 also conforms to 2.1 and 2.0.
| 版本 | 年份 | 备注 |
|---|---|---|
| WCAG 1.0 | 1999 | 首个W3C无障碍推荐标准 |
| WCAG 2.0 | 2008 | 重大重构,引入可测试的成功标准 |
| WCAG 2.1 | 2018 | 新增17项针对移动端、低视力、认知障碍的标准 |
| WCAG 2.2 | 2023 | 新增9项标准,移除4.1.1解析规则;现行标准 |
| WCAG 3.0 | ~2028 | 草案阶段;采用平实语言、以结果为导向的模型 |
向后兼容性:符合WCAG 2.2标准的内容同时符合2.1和2.0标准。
Part 2 — The Four POUR Principles
第2部分 — 四大POUR原则
Every WCAG success criterion maps to one of four principles:
每一项WCAG成功标准都对应以下四项原则之一:
1. Perceivable (P)
1. 可感知(Perceivable, P)
All information and UI components must be presentable in ways users can perceive.
- Text alternatives for non-text content
- Captions and audio descriptions for media
- Adaptable content presentation
- Sufficient color contrast and readability
所有信息和UI组件必须以用户可感知的方式呈现。
- 非文本内容提供文本替代方案
- 媒体提供字幕和音频描述
- 内容展示可适配不同设备
- 足够的颜色对比度和可读性
2. Operable (O)
2. 可操作(Operable, O)
All UI components and navigation must be operable.
- Full keyboard accessibility
- No keyboard traps
- Sufficient time for interactions
- No seizure-inducing content
- Multiple input modalities (keyboard, touch, voice)
- Accessible focus management
所有UI组件和导航必须可操作。
- 全键盘可访问
- 无键盘陷阱
- 足够的交互响应时间
- 无诱导癫痫发作的内容
- 多输入模态支持(键盘、触摸、语音)
- 可访问的焦点管理
3. Understandable (U)
3. 可理解(Understandable, U)
Users must understand the content and how the interface works.
- Readable and understandable text
- Predictable, consistent behavior
- Input assistance and error recovery
- Clear language and definitions
用户必须能理解内容以及界面的运作逻辑。
- 文本可读可理解
- 可预测的一致行为
- 输入辅助和错误恢复机制
- 清晰的语言和定义
4. Robust (R)
4. 健壮性(Robust, R)
Content must work reliably with current and future technologies, especially assistive technologies.
- Valid, well-formed markup
- Compatible with browsers and assistive technologies
- Proper semantic structure
内容必须能可靠适配当前及未来的技术,尤其是辅助技术。
- 有效、结构良好的标记
- 兼容浏览器和辅助技术
- 正确的语义结构
Part 3 — Conformance Levels
第3部分 — 合规等级
| Level | Criteria Count | Description |
|---|---|---|
| A | 32 | Minimum — basic accessibility, foundational compliance |
| AA | +24 (56 total) | Recommended — most legal requirements; addresses common barriers |
| AAA | +31 (87 total) | Enhanced — highest level; not always required |
Target: WCAG 2.2 AA — This is the level required by most accessibility laws (ADA, EN 301 549,
Section 508, Accessibility for Ontarians with Disabilities Act, etc.).
| 等级 | 标准数量 | 说明 |
|---|---|---|
| A | 32 | 最低等级——基础无障碍能力,合规的基石 |
| AA | +24(共56项) | 推荐等级——大多数法律要求的等级,解决常见的访问障碍 |
| AAA | +31(共87项) | 增强等级——最高等级,并非所有场景都要求 |
目标:WCAG 2.2 AA——这是大多数无障碍法规(ADA、EN 301 549、Section 508、安大略省残疾人无障碍法案等)要求的等级。
Part 4 — Complete WCAG 2.2 Success Criteria Reference
第4部分 — 完整WCAG 2.2成功标准参考
PRINCIPLE 1: PERCEIVABLE
原则1:可感知
Guideline 1.1 — Text Alternatives
指南1.1 — 文本替代方案
| Criterion | Level | Rule |
|---|---|---|
| 1.1.1 Non-text Content | A | All non-text content has a text alternative (images, icons, charts, buttons) |
| 标准 | 等级 | 规则 |
|---|---|---|
| 1.1.1 非文本内容 | A | 所有非文本内容(图片、图标、图表、按钮)都要有文本替代说明 |
Guideline 1.2 — Time-based Media
指南1.2 — 时基媒体
| Criterion | Level | Rule |
|---|---|---|
| 1.2.1 Audio-only and Video-only (Prerecorded) | A | Provide transcript or audio description |
| 1.2.2 Captions (Prerecorded) | A | Captions for all prerecorded audio in multimedia |
| 1.2.3 Audio Description or Media Alternative (Prerecorded) | A | Provide audio description or full text alternative |
| 1.2.4 Captions (Live) | AA | Captions for all live multimedia |
| 1.2.5 Audio Description (Prerecorded) | AA | Audio description for all prerecorded video |
| 1.2.6 Sign Language (Prerecorded) | AAA | Sign language interpretation for prerecorded audio |
| 1.2.7 Extended Audio Description (Prerecorded) | AAA | Extended audio description where pauses are insufficient |
| 1.2.8 Media Alternative (Prerecorded) | AAA | Full text alternative for all prerecorded media |
| 1.2.9 Audio-only (Live) | AAA | Alternative for all live audio-only content |
| 标准 | 等级 | 规则 |
|---|---|---|
| 1.2.1 纯音频/纯视频(预录制) | A | 提供文字脚本或音频描述 |
| 1.2.2 字幕(预录制) | A | 所有预录制多媒体中的音频都要有字幕 |
| 1.2.3 音频描述或媒体替代方案(预录制) | A | 提供音频描述或完整的文本替代方案 |
| 1.2.4 字幕(直播) | AA | 所有直播多媒体都要有字幕 |
| 1.2.5 音频描述(预录制) | AA | 所有预录制视频都要有音频描述 |
| 1.2.6 手语(预录制) | AAA | 预录制音频提供手语翻译 |
| 1.2.7 扩展音频描述(预录制) | AAA | 当视频停顿时间不足时提供扩展音频描述 |
| 1.2.8 媒体替代方案(预录制) | AAA | 所有预录制媒体都提供完整文本替代方案 |
| 1.2.9 纯音频(直播) | AAA | 所有直播纯音频内容提供替代方案 |
Guideline 1.3 — Adaptable
指南1.3 — 可适配
| Criterion | Level | Rule |
|---|---|---|
| 1.3.1 Info and Relationships | A | Structure and relationships conveyed through presentation must be programmatically determinable |
| 1.3.2 Meaningful Sequence | A | Reading and navigation order is logical |
| 1.3.3 Sensory Characteristics | A | Instructions don't rely solely on color, size, shape, visual location, or sound |
| 1.3.4 Orientation | AA | Content not restricted to portrait or landscape orientation |
| 1.3.5 Identify Input Purpose | AA | Input fields have programmatically identified purpose (autocomplete) |
| 1.3.6 Identify Purpose | AAA | Purpose of buttons, links, and controls can be programmatically determined |
| 标准 | 等级 | 规则 |
|---|---|---|
| 1.3.1 信息与关联关系 | A | 通过呈现传达的结构和关联关系必须可以通过程序识别 |
| 1.3.2 有意义的顺序 | A | 阅读和导航顺序符合逻辑 |
| 1.3.3 感官特征 | A | 操作说明不能仅依赖颜色、大小、形状、视觉位置或声音 |
| 1.3.4 方向 | AA | 内容不限制为竖屏或横屏显示 |
| 1.3.5 识别输入用途 | AA | 输入字段的用途可通过程序识别(支持自动填充) |
| 1.3.6 识别用途 | AAA | 按钮、链接和控件的用途可通过程序确定 |
Guideline 1.4 — Distinguishable
指南1.4 — 可区分
| Criterion | Level | Rule |
|---|---|---|
| 1.4.1 Use of Color | A | Color is not the only visual means of conveying information |
| 1.4.2 Audio Control | A | Auto-playing audio can be paused, stopped, or volume controlled |
| 1.4.3 Contrast (Minimum) | AA | 4.5:1 for normal text; 3:1 for large text |
| 1.4.4 Resize Text | AA | Text can be resized to 200% without loss of content |
| 1.4.5 Images of Text | AA | Use actual text instead of images of text where possible |
| 1.4.6 Contrast (Enhanced) | AAA | 7:1 for normal text; 4.5:1 for large text |
| 1.4.7 Low or No Background Audio | AAA | Audio-only content clearly audible over background |
| 1.4.8 Visual Presentation | AAA | Text width limited, line spacing adjustable, no full justification |
| 1.4.9 Images of Text (No Exception) | AAA | No images of text except logos |
| 1.4.10 Reflow | AA | Content presentable without horizontal scrolling at 320px wide |
| 1.4.11 Non-text Contrast | AA | UI components and graphical elements have 3:1 contrast ratio |
| 1.4.12 Text Spacing | AA | No loss of content when line height ≥1.5×, spacing ≥0.12em, word spacing ≥0.16em |
| 1.4.13 Content on Hover or Focus | AA | Hoverable/focusable content is dismissible, hoverable, and persistent |
| 标准 | 等级 | 规则 |
|---|---|---|
| 1.4.1 颜色使用 | A | 颜色不是传达信息的唯一视觉手段 |
| 1.4.2 音频控制 | A | 自动播放的音频可以暂停、停止或调整音量 |
| 1.4.3 对比度(最低要求) | AA | 普通文本对比度≥4.5:1;大文本对比度≥3:1 |
| 1.4.4 文本缩放 | AA | 文本可以放大到200%且不会丢失内容 |
| 1.4.5 文本图像 | AA | 尽可能使用真实文本而非文本图片 |
| 1.4.6 对比度(增强要求) | AAA | 普通文本对比度≥7:1;大文本对比度≥4.5:1 |
| 1.4.7 低背景音或无背景音 | AAA | 纯音频内容的音量明显高于背景音 |
| 1.4.8 视觉呈现 | AAA | 文本宽度受限、行间距可调整、不使用两端对齐 |
| 1.4.9 文本图像(无例外) | AAA | 除logo外不使用文本图像 |
| 1.4.10 重排 | AA | 页面宽度为320px时无需横向滚动即可展示全部内容 |
| 1.4.11 非文本对比度 | AA | UI组件和图形元素的对比度≥3:1 |
| 1.4.12 文本间距 | AA | 当行高≥1.5倍、字间距≥0.12em、词间距≥0.16em时内容不会丢失 |
| 1.4.13 悬停或聚焦时的内容 | AA | 可悬停/聚焦的内容可关闭、可悬停且不会自动消失 |
PRINCIPLE 2: OPERABLE
原则2:可操作
Guideline 2.1 — Keyboard Accessible
指南2.1 — 键盘可访问
| Criterion | Level | Rule |
|---|---|---|
| 2.1.1 Keyboard | A | All functionality operable via keyboard |
| 2.1.2 No Keyboard Trap | A | User can navigate away from any component using keyboard |
| 2.1.3 Keyboard (No Exception) | AAA | All functionality operable via keyboard — no exceptions |
| 2.1.4 Character Key Shortcuts | A | Single-character shortcuts can be disabled or remapped |
| 标准 | 等级 | 规则 |
|---|---|---|
| 2.1.1 键盘 | A | 所有功能都可以通过键盘操作 |
| 2.1.2 无键盘陷阱 | A | 用户可以通过键盘导航离开任何组件 |
| 2.1.3 键盘(无例外) | AAA | 所有功能都可以通过键盘操作,无例外 |
| 2.1.4 字符键快捷键 | A | 单字符快捷键可以禁用或重新映射 |
Guideline 2.2 — Enough Time
指南2.2 — 充足时间
| Criterion | Level | Rule |
|---|---|---|
| 2.2.1 Timing Adjustable | A | Time limits can be turned off, adjusted, or extended (≥10× default) |
| 2.2.2 Pause, Stop, Hide | A | Auto-moving/blinking/scrolling content can be paused, stopped, or hidden |
| 2.2.3 No Timing | AAA | No time restrictions except for real-time events |
| 2.2.4 Interruptions | AAA | User can postpone or suppress all interruptions |
| 2.2.5 Re-authenticating | AAA | No data lost when re-authenticating after timeout |
| 2.2.6 Timeouts | AAA | Users warned about session inactivity timeout |
| 标准 | 等级 | 规则 |
|---|---|---|
| 2.2.1 时间可调整 | A | 时间限制可以关闭、调整或延长(≥默认值的10倍) |
| 2.2.2 暂停、停止、隐藏 | A | 自动移动/闪烁/滚动的内容可以暂停、停止或隐藏 |
| 2.2.3 无时间限制 | AAA | 除实时事件外无时间限制 |
| 2.2.4 中断 | AAA | 用户可以推迟或屏蔽所有中断通知 |
| 2.2.5 重新认证 | AAA | 超时后重新认证不会丢失已填写数据 |
| 2.2.6 超时提醒 | AAA | 会话非活动超时前会提醒用户 |
Guideline 2.3 — Seizures and Physical Reactions
指南2.3 — 癫痫和身体反应
| Criterion | Level | Rule |
|---|---|---|
| 2.3.1 Three Flashes or Below Threshold | A | No flashing content more than 3 times/second (or below threshold) |
| 2.3.2 Three Flashes | AAA | All content restricted to ≤3 flashes/second |
| 2.3.3 Animation from Interactions | AAA | Motion animation triggered by interaction can be disabled |
| 标准 | 等级 | 规则 |
|---|---|---|
| 2.3.1 三次闪光或低于阈值 | A | 无每秒闪烁超过3次的内容(或低于安全阈值) |
| 2.3.2 三次闪光 | AAA | 所有内容每秒闪光次数≤3次 |
| 2.3.3 交互触发的动画 | AAA | 交互触发的动效可以禁用 |
Guideline 2.4 — Navigable
指南2.4 — 可导航
| Criterion | Level | Rule |
|---|---|---|
| 2.4.1 Bypass Blocks | A | Mechanism to skip repeated blocks (skip nav link) |
| 2.4.2 Page Titled | A | Web pages have descriptive titles |
| 2.4.3 Focus Order | A | Focus order is logical and meaningful |
| 2.4.4 Link Purpose (In Context) | A | Link purpose clear from link text or context |
| 2.4.5 Multiple Ways | AA | Multiple ways to locate a page (search, sitemap, navigation) |
| 2.4.6 Headings and Labels | AA | Headings and labels describe topic or purpose |
| 2.4.7 Focus Visible | AA | Keyboard focus indicator is visible |
| 2.4.8 Location | AAA | User knows their location within a set of pages |
| 2.4.9 Link Purpose (Link Only) | AAA | Link purpose clear from link text alone |
| 2.4.10 Section Headings | AAA | Section headings organize content |
| 2.4.11 Focus Not Obscured (Minimum) ⭐ NEW 2.2 | AA | Focused element not entirely hidden by sticky/fixed content |
| 2.4.12 Focus Not Obscured (Enhanced) ⭐ NEW 2.2 | AAA | Focused element fully visible |
| 2.4.13 Focus Appearance ⭐ NEW 2.2 | AAA | Focus indicator: ≥2px outline, ≥3:1 contrast change |
| 标准 | 等级 | 规则 |
|---|---|---|
| 2.4.1 跳过区块 | A | 提供跳过重复区块的机制(跳过导航链接) |
| 2.4.2 页面标题 | A | 网页有描述性的标题 |
| 2.4.3 焦点顺序 | A | 焦点顺序逻辑合理且有意义 |
| 2.4.4 链接用途(上下文内) | A | 链接用途可通过链接文本或上下文明确 |
| 2.4.5 多种访问方式 | AA | 提供多种查找页面的方式(搜索、站点地图、导航) |
| 2.4.6 标题和标签 | AA | 标题和标签能描述主题或用途 |
| 2.4.7 焦点可见 | AA | 键盘焦点指示器可见 |
| 2.4.8 位置提示 | AAA | 用户可以知道自己在页面集合中的位置 |
| 2.4.9 链接用途(仅链接文本) | AAA | 仅通过链接文本即可明确链接用途 |
| 2.4.10 章节标题 | AAA | 章节标题用于组织内容 |
| 2.4.11 焦点不被遮挡(最低要求)⭐ 2.2新增 | AA | 聚焦元素不会被粘性/固定内容完全遮挡 |
| 2.4.12 焦点不被遮挡(增强要求)⭐ 2.2新增 | AAA | 聚焦元素完全可见 |
| 2.4.13 焦点外观 ⭐ 2.2新增 | AAA | 焦点指示器:≥2px边框,≥3:1的对比度变化 |
Guideline 2.5 — Input Modalities
指南2.5 — 输入模态
| Criterion | Level | Rule |
|---|---|---|
| 2.5.1 Pointer Gestures | A | Path-based gestures have single-pointer alternative |
| 2.5.2 Pointer Cancellation | A | Pointer actions activate on "up" event, not "down" |
| 2.5.3 Label in Name | A | Accessible name contains the visible label text |
| 2.5.4 Motion Actuation | A | Motion-triggered functions have UI alternative and can be disabled |
| 2.5.5 Target Size (Enhanced) | AAA | Touch targets ≥44×44 CSS pixels |
| 2.5.6 Concurrent Input Mechanisms | AAA | No restriction on input modality |
| 2.5.7 Dragging Movements ⭐ NEW 2.2 | AA | Drag-only functionality has single-pointer alternative |
| 2.5.8 Target Size (Minimum) ⭐ NEW 2.2 | AA | Touch targets ≥24×24 CSS pixels or adequate spacing |
| 标准 | 等级 | 规则 |
|---|---|---|
| 2.5.1 指针手势 | A | 基于路径的手势提供单指操作替代方案 |
| 2.5.2 指针取消 | A | 指针操作在"抬起"事件时触发,而非"按下"事件 |
| 2.5.3 名称包含标签 | A | 可访问名称包含可见的标签文本 |
| 2.5.4 动作触发 | A | 动作触发的功能提供UI替代方案且可禁用 |
| 2.5.5 目标大小(增强要求) | AAA | 触摸目标≥44×44 CSS像素 |
| 2.5.6 并发输入机制 | AAA | 不限制输入模态 |
| 2.5.7 拖拽操作 ⭐ 2.2新增 | AA | 仅支持拖拽的功能提供单指操作替代方案 |
| 2.5.8 目标大小(最低要求)⭐ 2.2新增 | AA | 触摸目标≥24×24 CSS像素或有足够间距 |
PRINCIPLE 3: UNDERSTANDABLE
原则3:可理解
Guideline 3.1 — Readable
指南3.1 — 可读
| Criterion | Level | Rule |
|---|---|---|
| 3.1.1 Language of Page | A | Default human language programmatically identified (lang attribute) |
| 3.1.2 Language of Parts | AA | Language changes in content are marked |
| 3.1.3 Unusual Words | AAA | Definitions for jargon, idioms, technical terms |
| 3.1.4 Abbreviations | AAA | Abbreviations expanded on first use |
| 3.1.5 Reading Level | AAA | Text at lower secondary education level or simplified version available |
| 3.1.6 Pronunciation | AAA | Pronunciation provided for ambiguous words |
| 标准 | 等级 | 规则 |
|---|---|---|
| 3.1.1 页面语言 | A | 通过lang属性标记默认的人类语言 |
| 3.1.2 内容片段语言 | AA | 内容中的语言变化会被标记 |
| 3.1.3 特殊词汇 | AAA | 提供行话、习语、技术术语的定义 |
| 3.1.4 缩写 | AAA | 缩写首次出现时展开全称 |
| 3.1.5 阅读水平 | AAA | 文本难度不超过初中教育水平,或提供简化版本 |
| 3.1.6 发音 | AAA | 为有歧义的词语提供发音说明 |
Guideline 3.2 — Predictable
指南3.2 — 可预测
| Criterion | Level | Rule |
|---|---|---|
| 3.2.1 On Focus | A | No context change when component receives focus |
| 3.2.2 On Input | A | Changing settings doesn't automatically submit form |
| 3.2.3 Consistent Navigation | AA | Navigation mechanisms in same relative order across pages |
| 3.2.4 Consistent Identification | AA | Components with same function identified consistently |
| 3.2.5 Change on Request | AAA | Context changes only at user request |
| 3.2.6 Consistent Help ⭐ NEW 2.2 | A | Help mechanisms in same location across pages |
| 标准 | 等级 | 规则 |
|---|---|---|
| 3.2.1 获得焦点时 | A | 组件获得焦点时不会触发上下文变化 |
| 3.2.2 输入时 | A | 修改设置不会自动提交表单 |
| 3.2.3 一致的导航 | AA | 导航机制在不同页面的相对位置一致 |
| 3.2.4 一致的标识 | AA | 功能相同的组件标识一致 |
| 3.2.5 按请求变更 | AAA | 仅在用户请求时才触发上下文变化 |
| 3.2.6 一致的帮助 ⭐ 2.2新增 | A | 帮助机制在不同页面的位置一致 |
Guideline 3.3 — Input Assistance
指南3.3 — 输入辅助
| Criterion | Level | Rule |
|---|---|---|
| 3.3.1 Error Identification | A | Errors identified and described in text |
| 3.3.2 Labels or Instructions | A | Labels or instructions provided for all inputs |
| 3.3.3 Error Suggestion | AA | Suggestions provided for input errors where known |
| 3.3.4 Error Prevention (Legal, Financial, Data) | AA | Critical submissions are reversible, checked, or confirmed |
| 3.3.5 Help | AAA | Context-sensitive help available |
| 3.3.6 Error Prevention (All) | AAA | All inputs can be reversed, checked, or confirmed |
| 3.3.7 Redundant Entry ⭐ NEW 2.2 | A | Previously entered info not required again in same session |
| 3.3.8 Accessible Authentication (Minimum) ⭐ NEW 2.2 | AA | Authentication without cognitive function test or memory requirement |
| 3.3.9 Accessible Authentication (Enhanced) ⭐ NEW 2.2 | AAA | Enhanced alternatives to cognitive function tests |
| 标准 | 等级 | 规则 |
|---|---|---|
| 3.3.1 错误识别 | A | 错误会被识别并以文本形式描述 |
| 3.3.2 标签或说明 | A | 所有输入项都提供标签或操作说明 |
| 3.3.3 错误建议 | AA | 已知输入错误会提供修正建议 |
| 3.3.4 错误预防(法律、金融、数据) | AA | 重要提交可撤销、可检查或需确认 |
| 3.3.5 帮助 | AAA | 提供上下文相关的帮助 |
| 3.3.6 错误预防(所有) | AAA | 所有输入都可撤销、可检查或需确认 |
| 3.3.7 重复输入 ⭐ 2.2新增 | A | 同一会话中不需要重复输入之前填写过的信息 |
| 3.3.8 可访问认证(最低要求)⭐ 2.2新增 | AA | 认证不需要认知功能测试或记忆要求 |
| 3.3.9 可访问认证(增强要求)⭐ 2.2新增 | AAA | 提供认知功能测试的增强替代方案 |
PRINCIPLE 4: ROBUST
原则4:健壮性
Guideline 4.1 — Compatible
指南4.1 — 兼容性
| Criterion | Level | Rule |
|---|---|---|
| Removed in WCAG 2.2 — obsolete due to HTML5 error correction | ||
| 4.1.2 Name, Role, Value | A | All components have accessible name, role, and state/value |
| 4.1.3 Status Messages | AA | Status messages announced to screen readers without focus change |
| 标准 | 等级 | 规则 |
|---|---|---|
| WCAG 2.2已移除——因HTML5错误纠正机制已过时 | ||
| 4.1.2 名称、角色、值 | A | 所有组件都有可访问的名称、角色和状态/值 |
| 4.1.3 状态消息 | AA | 状态消息无需焦点变化即可被屏幕阅读器播报 |
Part 5 — Implementation Reference
第5部分 — 实现参考
5.1 Color Contrast Rules
5.1 颜色对比度规则
| Context | AA Minimum | AAA Enhanced |
|---|---|---|
| Normal text (<18px or <14px bold) | 4.5:1 | 7:1 |
| Large text (≥18px or ≥14px bold) | 3:1 | 4.5:1 |
| UI components & graphics | 3:1 | 3:1 |
| Placeholder text | 4.5:1 | — |
| Disabled elements | Exempt | Exempt |
| Decorative elements | Exempt | Exempt |
Dark Mode Note: Dark themes must still meet contrast ratios. Avoid pure black
(causes halation/eye strain); use soft blacks like or .
High-saturation colors on dark backgrounds may vibrate visually — reduce saturation.
#000000#0f0f0f#121212Tools: WebAIM Contrast Checker, Colour Contrast Analyser, axe DevTools, Chrome DevTools.
| 场景 | AA最低要求 | AAA增强要求 |
|---|---|---|
| 普通文本(<18px或<14px粗体) | 4.5:1 | 7:1 |
| 大文本(≥18px或≥14px粗体) | 3:1 | 4.5:1 |
| UI组件和图形 | 3:1 | 3:1 |
| 占位符文本 | 4.5:1 | — |
| 禁用元素 | 豁免 | 豁免 |
| 装饰元素 | 豁免 | 豁免 |
**深色模式注意事项:**深色主题仍需满足对比度要求。避免使用纯黑色(会导致光晕/眼疲劳);使用柔和的黑色如或。深色背景上的高饱和度颜色可能会产生视觉抖动——降低饱和度即可解决。
#000000#0f0f0f#121212工具: WebAIM对比度检查器、颜色对比度分析器、axe DevTools、Chrome DevTools。
5.2 Semantic HTML — Use Native Elements First
5.2 语义化HTML — 优先使用原生元素
Always prefer semantic HTML over ARIA. ARIA is a supplement, not a replacement.
html
<!-- ✅ CORRECT: Semantic HTML -->
<header>…</header>
<nav aria-label="Main navigation">…</nav>
<main>
<article>…</article>
<aside>…</aside>
</main>
<footer>…</footer>
<!-- ❌ WRONG: div soup -->
<div class="header">…</div>
<div class="nav">…</div>Semantic element → landmark mapping:
| Element | ARIA Landmark Role |
|---|---|
| |
| |
| |
| |
| |
| |
| |
Heading hierarchy rule: Never skip levels. → → (not h1 → h3).
Multiple elements are acceptable but first should be page/section title.
<h1><h2><h3><h1>始终优先选择语义化HTML而非ARIA。ARIA是补充,而非替代品。
html
<!-- ✅ CORRECT: Semantic HTML -->
<header>…</header>
<nav aria-label="Main navigation">…</nav>
<main>
<article>…</article>
<aside>…</aside>
</main>
<footer>…</footer>
<!-- ❌ WRONG: div soup -->
<div class="header">…</div>
<div class="nav">…</div>语义化元素→地标角色映射:
| 元素 | ARIA地标角色 |
|---|---|
| |
| |
| |
| |
| |
| |
| |
**标题层级规则:**不要跳过层级。按→→的顺序使用(不要从h1直接跳到h3)。允许页面存在多个元素,但第一个h1应该是页面/章节标题。
<h1><h2><h3><h1>5.3 WAI-ARIA Quick Reference
5.3 WAI-ARIA快速参考
Use ARIA only when semantic HTML is insufficient. The First Rule of ARIA: don't use ARIA
if you can use a native HTML element or attribute with the semantics built in.
仅当语义化HTML无法满足需求时才使用ARIA。ARIA第一原则:如果你可以使用自带语义的原生HTML元素或属性,就不要使用ARIA。
Landmark Roles
地标角色
html
<div role="banner">…</div> <!-- Same as <header> -->
<div role="navigation">…</div> <!-- Same as <nav> -->
<div role="main">…</div> <!-- Same as <main> -->
<div role="complementary">…</div> <!-- Same as <aside> -->
<div role="contentinfo">…</div> <!-- Same as <footer> -->
<div role="search">…</div> <!-- Search region -->
<div role="region" aria-label="…">…</div> <!-- Generic named region -->html
<div role="banner">…</div> <!-- Same as <header> -->
<div role="navigation">…</div> <!-- Same as <nav> -->
<div role="main">…</div> <!-- Same as <main> -->
<div role="complementary">…</div> <!-- Same as <aside> -->
<div role="contentinfo">…</div> <!-- Same as <footer> -->
<div role="search">…</div> <!-- Search region -->
<div role="region" aria-label="…">…</div> <!-- Generic named region -->Widget Roles (Interactive Components)
组件角色(交互组件)
html
role="button" <!-- Clickable element -->
role="checkbox" <!-- Checkable input -->
role="radio" <!-- Radio button -->
role="combobox" <!-- Dropdown / autocomplete -->
role="listbox" <!-- List for selection -->
role="option" <!-- Item within listbox -->
role="menu" <!-- Menu container -->
role="menuitem" <!-- Menu item -->
role="tab" <!-- Tab button -->
role="tablist" <!-- Tab container -->
role="tabpanel" <!-- Tab content panel -->
role="dialog" <!-- Modal dialog -->
role="alertdialog" <!-- Alert modal -->
role="slider" <!-- Range input -->
role="progressbar" <!-- Progress indicator -->
role="tooltip" <!-- Tooltip -->
role="tree" <!-- Tree widget -->
role="treeitem" <!-- Tree item -->
role="grid" <!-- Interactive data grid -->
role="gridcell" <!-- Grid cell -->html
role="button" <!-- Clickable element -->
role="checkbox" <!-- Checkable input -->
role="radio" <!-- Radio button -->
role="combobox" <!-- Dropdown / autocomplete -->
role="listbox" <!-- List for selection -->
role="option" <!-- Item within listbox -->
role="menu" <!-- Menu container -->
role="menuitem" <!-- Menu item -->
role="tab" <!-- Tab button -->
role="tablist" <!-- Tab container -->
role="tabpanel" <!-- Tab content panel -->
role="dialog" <!-- Modal dialog -->
role="alertdialog" <!-- Alert modal -->
role="slider" <!-- Range input -->
role="progressbar" <!-- Progress indicator -->
role="tooltip" <!-- Tooltip -->
role="tree" <!-- Tree widget -->
role="treeitem" <!-- Tree item -->
role="grid" <!-- Interactive data grid -->
role="gridcell" <!-- Grid cell -->Live Region Roles (Dynamic Content)
动态区域角色(动态内容)
html
role="alert" <!-- Assertive: important time-sensitive info -->
role="status" <!-- Polite: advisory info (status messages) -->
role="log" <!-- Polite: ordered sequence of updates -->
role="timer" <!-- Timer announcements -->
<!-- Equivalent ARIA live properties -->
aria-live="polite" <!-- Announces after current speech -->
aria-live="assertive" <!-- Interrupts current speech (use sparingly) -->
aria-live="off" <!-- No announcements (default) -->
aria-atomic="true" <!-- Announce entire region on update -->
aria-relevant="additions text" <!-- What triggers announcement -->html
role="alert" <!-- Assertive: important time-sensitive info -->
role="status" <!-- Polite: advisory info (status messages) -->
role="log" <!-- Polite: ordered sequence of updates -->
role="timer" <!-- Timer announcements -->
<!-- Equivalent ARIA live properties -->
aria-live="polite" <!-- Announces after current speech -->
aria-live="assertive" <!-- Interrupts current speech (use sparingly) -->
aria-live="off" <!-- No announcements (default) -->
aria-atomic="true" <!-- Announce entire region on update -->
aria-relevant="additions text" <!-- What triggers announcement -->Essential ARIA Properties
核心ARIA属性
html
<!-- Labeling -->
aria-label="Close dialog"
aria-labelledby="heading-id"
aria-describedby="description-id help-text-id"
<!-- State -->
aria-expanded="true|false" <!-- Collapsible element open state -->
aria-selected="true|false" <!-- Selection state -->
aria-checked="true|false|mixed" <!-- Checkbox/switch state -->
aria-pressed="true|false|mixed" <!-- Toggle button state -->
aria-disabled="true" <!-- Disabled state -->
aria-hidden="true" <!-- Hidden from AT -->
aria-invalid="true|false|grammar|spelling" <!-- Validation state -->
aria-busy="true|false" <!-- Loading state -->
<!-- Relationships -->
aria-controls="panel-id" <!-- Controls another element -->
aria-owns="list-id" <!-- Owns child elements -->
aria-haspopup="true|menu|listbox|tree|grid|dialog" <!-- Has popup -->
aria-autocomplete="none|inline|list|both" <!-- Autocomplete behavior -->
<!-- Range -->
aria-valuemin="0"
aria-valuemax="100"
aria-valuenow="50"
aria-valuetext="50 percent" <!-- Human-readable value -->
<!-- Current location -->
aria-current="page|step|location|date|time|true|false"html
<!-- Labeling -->
aria-label="Close dialog"
aria-labelledby="heading-id"
aria-describedby="description-id help-text-id"
<!-- State -->
aria-expanded="true|false" <!-- Collapsible element open state -->
aria-selected="true|false" <!-- Selection state -->
aria-checked="true|false|mixed" <!-- Checkbox/switch state -->
aria-pressed="true|false|mixed" <!-- Toggle button state -->
aria-disabled="true" <!-- Disabled state -->
aria-hidden="true" <!-- Hidden from AT -->
aria-invalid="true|false|grammar|spelling" <!-- Validation state -->
aria-busy="true|false" <!-- Loading state -->
<!-- Relationships -->
aria-controls="panel-id" <!-- Controls another element -->
aria-owns="list-id" <!-- Owns child elements -->
aria-haspopup="true|menu|listbox|tree|grid|dialog" <!-- Has popup -->
aria-autocomplete="none|inline|list|both" <!-- Autocomplete behavior -->
<!-- Range -->
aria-valuemin="0"
aria-valuemax="100"
aria-valuenow="50"
aria-valuetext="50 percent" <!-- Human-readable value -->
<!-- Current location -->
aria-current="page|step|location|date|time|true|false"5.4 Keyboard Navigation Implementation
5.4 键盘导航实现
Every interactive component must be fully keyboard-accessible.
每个交互组件必须完全支持键盘访问。
Focus Management Rules
焦点管理规则
css
/* NEVER do this without a custom replacement */
*:focus { outline: none; }
/* ✅ Custom focus indicator — meets WCAG 2.4.7 and 2.4.13 */
:focus-visible {
outline: 2px solid #005fcc;
outline-offset: 2px;
border-radius: 2px;
}
/* Different styles for mouse vs keyboard */
:focus:not(:focus-visible) { outline: none; }
:focus-visible { outline: 2px solid #005fcc; outline-offset: 2px; }css
/* NEVER do this without a custom replacement */
*:focus { outline: none; }
/* ✅ Custom focus indicator — meets WCAG 2.4.7 and 2.4.13 */
:focus-visible {
outline: 2px solid #005fcc;
outline-offset: 2px;
border-radius: 2px;
}
/* Different styles for mouse vs keyboard */
:focus:not(:focus-visible) { outline: none; }
:focus-visible { outline: 2px solid #005fcc; outline-offset: 2px; }Tab Order
Tab顺序
html
<!-- ✅ Natural DOM order (preferred) -->
<!-- ✅ Use tabindex="0" to add element to tab order -->
<div role="button" tabindex="0">Custom Button</div>
<!-- ❌ NEVER use positive tabindex (breaks natural order) -->
<button tabindex="3">Bad</button>
<!-- Remove from tab order (but still scriptable) -->
<div tabindex="-1" id="modal-content">…</div>html
<!-- ✅ Natural DOM order (preferred) -->
<!-- ✅ Use tabindex="0" to add element to tab order -->
<div role="button" tabindex="0">Custom Button</div>
<!-- ❌ NEVER use positive tabindex (breaks natural order) -->
<button tabindex="3">Bad</button>
<!-- Remove from tab order (but still scriptable) -->
<div tabindex="-1" id="modal-content">…</div>Skip Navigation Link
跳过导航链接
html
<!-- First element in <body> — visible on focus -->
<a href="#main-content" class="skip-link">Skip to main content</a>
<style>
.skip-link {
position: absolute;
top: -100%;
left: 0;
padding: 0.5rem 1rem;
background: #000;
color: #fff;
z-index: 9999;
transition: top 0.1s;
}
.skip-link:focus { top: 0; }
</style>
<main id="main-content">…</main>html
<!-- First element in <body> — visible on focus -->
<a href="#main-content" class="skip-link">Skip to main content</a>
<style>
.skip-link {
position: absolute;
top: -100%;
left: 0;
padding: 0.5rem 1rem;
background: #000;
color: #fff;
z-index: 9999;
transition: top 0.1s;
}
.skip-link:focus { top: 0; }
</style>
<main id="main-content">…</main>Keyboard Patterns by Component
各组件键盘交互模式
| Component | Key | Action |
|---|---|---|
| All | Tab | Move focus forward |
| All | Shift+Tab | Move focus backward |
| Button | Enter / Space | Activate |
| Link | Enter | Follow link |
| Checkbox | Space | Toggle |
| Radio Group | Arrow Keys | Select option |
| Select/Dropdown | Arrow Keys | Navigate; Enter select |
| Dialog | Escape | Close |
| Dialog | Tab | Cycle within dialog only |
| Menu | Arrow Keys | Navigate items |
| Menu | Escape | Close |
| Menu | Enter / Space | Activate item |
| Slider | Arrow Keys | Increment/Decrement |
| Slider | Home / End | Min / Max value |
| Tabs | Arrow Keys | Switch tabs |
| Tree | Arrow Keys | Expand/collapse/navigate |
| 组件 | 按键 | 动作 |
|---|---|---|
| 所有组件 | Tab | 向前移动焦点 |
| 所有组件 | Shift+Tab | 向后移动焦点 |
| 按钮 | Enter / Space | 触发操作 |
| 链接 | Enter | 跳转链接 |
| 复选框 | Space | 切换选中状态 |
| 单选组 | 方向键 | 选择选项 |
| 选择器/下拉框 | 方向键 | 导航;Enter确认选择 |
| 弹窗 | Escape | 关闭 |
| 弹窗 | Tab | 仅在弹窗内循环焦点 |
| 菜单 | 方向键 | 导航菜单项 |
| 菜单 | Escape | 关闭 |
| 菜单 | Enter / Space | 触发菜单项 |
| 滑块 | 方向键 | 增减值 |
| 滑块 | Home / End | 调到最小/最大值 |
| 标签页 | 方向键 | 切换标签 |
| 树形控件 | 方向键 | 展开/收起/导航 |
Focus Trap for Modals
弹窗焦点陷阱
javascript
// Trap focus within modal while open
function trapFocus(modal) {
const focusable = modal.querySelectorAll(
'a[href], button:not([disabled]), textarea, input, select, [tabindex]:not([tabindex="-1"])'
);
const firstEl = focusable[0];
const lastEl = focusable[focusable.length - 1];
modal.addEventListener('keydown', (e) => {
if (e.key !== 'Tab') return;
if (e.shiftKey) {
if (document.activeElement === firstEl) {
e.preventDefault(); lastEl.focus();
}
} else {
if (document.activeElement === lastEl) {
e.preventDefault(); firstEl.focus();
}
}
});
}javascript
// Trap focus within modal while open
function trapFocus(modal) {
const focusable = modal.querySelectorAll(
'a[href], button:not([disabled]), textarea, input, select, [tabindex]:not([tabindex="-1"])'
);
const firstEl = focusable[0];
const lastEl = focusable[focusable.length - 1];
modal.addEventListener('keydown', (e) => {
if (e.key !== 'Tab') return;
if (e.shiftKey) {
if (document.activeElement === firstEl) {
e.preventDefault(); lastEl.focus();
}
} else {
if (document.activeElement === lastEl) {
e.preventDefault(); firstEl.focus();
}
}
});
}5.5 Accessible Component Patterns
5.5 可访问组件模式
Modal / Dialog
模态框/弹窗
html
<dialog
role="dialog"
aria-modal="true"
aria-labelledby="modal-title"
aria-describedby="modal-desc"
id="my-modal"
>
<h2 id="modal-title">Confirm Action</h2>
<p id="modal-desc">Are you sure you want to delete this item?</p>
<button type="button" autofocus>Cancel</button>
<button type="button">Delete</button>
</dialog>javascript
// HTML5 <dialog> — built-in focus management + Escape handling
const modal = document.getElementById('my-modal');
const trigger = document.getElementById('open-btn');
trigger.addEventListener('click', () => modal.showModal());
modal.addEventListener('close', () => trigger.focus()); // Restore focushtml
<dialog
role="dialog"
aria-modal="true"
aria-labelledby="modal-title"
aria-describedby="modal-desc"
id="my-modal"
>
<h2 id="modal-title">Confirm Action</h2>
<p id="modal-desc">Are you sure you want to delete this item?</p>
<button type="button" autofocus>Cancel</button>
<button type="button">Delete</button>
</dialog>javascript
// HTML5 <dialog> — built-in focus management + Escape handling
const modal = document.getElementById('my-modal');
const trigger = document.getElementById('open-btn');
trigger.addEventListener('click', () => modal.showModal());
modal.addEventListener('close', () => trigger.focus()); // Restore focusAccessible Button (Custom)
可访问按钮(自定义)
html
<!-- Prefer <button> whenever possible -->
<button type="button" aria-pressed="false" id="dark-toggle">
<svg aria-hidden="true" focusable="false">…</svg>
Dark Mode
</button>
<!-- Icon-only button: needs aria-label -->
<button type="button" aria-label="Close dialog">
<svg aria-hidden="true" focusable="false">…</svg>
</button>html
<!-- Prefer <button> whenever possible -->
<button type="button" aria-pressed="false" id="dark-toggle">
<svg aria-hidden="true" focusable="false">…</svg>
Dark Mode
</button>
<!-- Icon-only button: needs aria-label -->
<button type="button" aria-label="Close dialog">
<svg aria-hidden="true" focusable="false">…</svg>
</button>Accordion
手风琴组件
html
<div class="accordion">
<h3>
<button
type="button"
aria-expanded="false"
aria-controls="panel-1"
id="btn-1"
>Section Title</button>
</h3>
<div id="panel-1" role="region" aria-labelledby="btn-1" hidden>
Panel content here
</div>
</div>html
<div class="accordion">
<h3>
<button
type="button"
aria-expanded="false"
aria-controls="panel-1"
id="btn-1"
>Section Title</button>
</h3>
<div id="panel-1" role="region" aria-labelledby="btn-1" hidden>
Panel content here
</div>
</div>Tabs
标签页
html
<div role="tablist" aria-label="Settings sections">
<button role="tab" aria-selected="true" aria-controls="panel-a" id="tab-a" tabindex="0">General</button>
<button role="tab" aria-selected="false" aria-controls="panel-b" id="tab-b" tabindex="-1">Privacy</button>
</div>
<div role="tabpanel" id="panel-a" aria-labelledby="tab-a">…</div>
<div role="tabpanel" id="panel-b" aria-labelledby="tab-b" hidden>…</div>html
<div role="tablist" aria-label="Settings sections">
<button role="tab" aria-selected="true" aria-controls="panel-a" id="tab-a" tabindex="0">General</button>
<button role="tab" aria-selected="false" aria-controls="panel-b" id="tab-b" tabindex="-1">Privacy</button>
</div>
<div role="tabpanel" id="panel-a" aria-labelledby="tab-a">…</div>
<div role="tabpanel" id="panel-b" aria-labelledby="tab-b" hidden>…</div>Combobox / Autocomplete
组合框/自动完成
html
<label for="city-input">City</label>
<input
type="text"
id="city-input"
role="combobox"
aria-expanded="false"
aria-haspopup="listbox"
aria-autocomplete="list"
aria-controls="city-list"
/>
<ul id="city-list" role="listbox" aria-label="Cities">
<li role="option" id="opt-1">New York</li>
<li role="option" id="opt-2">Los Angeles</li>
</ul>html
<label for="city-input">City</label>
<input
type="text"
id="city-input"
role="combobox"
aria-expanded="false"
aria-haspopup="listbox"
aria-autocomplete="list"
aria-controls="city-list"
/>
<ul id="city-list" role="listbox" aria-label="Cities">
<li role="option" id="opt-1">New York</li>
<li role="option" id="opt-2">Los Angeles</li>
</ul>Alert / Status Message
提醒/状态消息
html
<!-- Polite announcement (most cases) -->
<div role="status" aria-live="polite" aria-atomic="true">
Form saved successfully.
</div>
<!-- Assertive announcement (errors only) -->
<div role="alert" aria-live="assertive" aria-atomic="true">
Error: Please enter a valid email address.
</div>html
<!-- Polite announcement (most cases) -->
<div role="status" aria-live="polite" aria-atomic="true">
Form saved successfully.
</div>
<!-- Assertive announcement (errors only) -->
<div role="alert" aria-live="assertive" aria-atomic="true">
Error: Please enter a valid email address.
</div>5.6 Forms — Accessible Patterns
5.6 表单 — 可访问模式
html
<!-- ✅ Complete accessible form field -->
<div class="field">
<label for="email">
Email address
<span aria-hidden="true" class="required">*</span>
<span class="sr-only">(required)</span>
</label>
<input
type="email"
id="email"
name="email"
autocomplete="email"
aria-required="true"
aria-describedby="email-hint email-error"
aria-invalid="false"
/>
<p id="email-hint" class="hint">We'll never share your email.</p>
<p id="email-error" class="error" role="alert" hidden>
Please enter a valid email address.
</p>
</div>
<!-- ✅ Grouped radio buttons -->
<fieldset>
<legend>Notification preferences</legend>
<label><input type="radio" name="notif" value="email"> Email</label>
<label><input type="radio" name="notif" value="sms"> SMS</label>
<label><input type="radio" name="notif" value="none"> None</label>
</fieldset>Form validation rules:
- Validate on or
blur, not on every keystrokesubmit - Mark invalid fields with
aria-invalid="true" - Link error messages to fields via
aria-describedby - Use on dynamically inserted error messages
role="alert" - Never use placeholder text as the only label
- Provide autocomplete attributes for common fields
html
<!-- ✅ Complete accessible form field -->
<div class="field">
<label for="email">
Email address
<span aria-hidden="true" class="required">*</span>
<span class="sr-only">(required)</span>
</label>
<input
type="email"
id="email"
name="email"
autocomplete="email"
aria-required="true"
aria-describedby="email-hint email-error"
aria-invalid="false"
/>
<p id="email-hint" class="hint">We'll never share your email.</p>
<p id="email-error" class="error" role="alert" hidden>
Please enter a valid email address.
</p>
</div>
<!-- ✅ Grouped radio buttons -->
<fieldset>
<legend>Notification preferences</legend>
<label><input type="radio" name="notif" value="email"> Email</label>
<label><input type="radio" name="notif" value="sms"> SMS</label>
<label><input type="radio" name="notif" value="none"> None</label>
</fieldset>表单验证规则:
- 在或
blur事件时验证,不要每输入一个字符就验证submit - 用标记无效字段
aria-invalid="true" - 通过将错误消息关联到对应字段
aria-describedby - 动态插入的错误消息使用
role="alert" - 不要将占位符文本作为唯一标签
- 为常用字段提供自动填充属性
5.7 Images and Alt Text
5.7 图片和Alt文本
html
<!-- ✅ Informative image -->
<img src="chart.png" alt="Sales by region 2024: North 35%, South 28%, East 22%, West 15%">
<!-- ✅ Decorative image — empty alt required -->
<img src="divider.png" alt="">
<!-- ✅ Icon button — label on button, not image -->
<button aria-label="Search">
<img src="magnifier.svg" alt="">
</button>
<!-- ✅ Complex diagram — short alt + detailed description -->
<figure>
<img src="architecture.png" alt="System architecture diagram" aria-describedby="arch-desc">
<figcaption id="arch-desc">
Three-tier architecture: client tier connects to API gateway,
which routes to microservices cluster, backed by PostgreSQL and Redis.
</figcaption>
</figure>
<!-- ✅ CSS background image (decorative) — no alt needed -->
<div class="hero-bg" role="img" aria-label="Abstract blue wave">…</div>
<!-- OR if purely decorative: aria-hidden="true" -->Alt text guidelines:
- Keep concise (≤125 characters typical; up to 250 for complex)
- Don't start with "Image of" or "Picture of"
- Describe purpose and content, not appearance alone
- For charts: include key data points
- For logos: use company name only
html
<!-- ✅ Informative image -->
<img src="chart.png" alt="Sales by region 2024: North 35%, South 28%, East 22%, West 15%">
<!-- ✅ Decorative image — empty alt required -->
<img src="divider.png" alt="">
<!-- ✅ Icon button — label on button, not image -->
<button aria-label="Search">
<img src="magnifier.svg" alt="">
</button>
<!-- ✅ Complex diagram — short alt + detailed description -->
<figure>
<img src="architecture.png" alt="System architecture diagram" aria-describedby="arch-desc">
<figcaption id="arch-desc">
Three-tier architecture: client tier connects to API gateway,
which routes to microservices cluster, backed by PostgreSQL and Redis.
</figcaption>
</figure>
<!-- ✅ CSS background image (decorative) — no alt needed -->
<div class="hero-bg" role="img" aria-label="Abstract blue wave">…</div>
<!-- OR if purely decorative: aria-hidden="true" -->Alt文本指导原则:
- 保持简洁(通常≤125字符;复杂内容最多250字符)
- 不要以"图片为"或"照片为"开头
- 描述用途和内容,而不仅仅是外观
- 图表要包含关键数据点
- Logo仅使用公司名称作为alt文本
5.8 Typography Accessibility
5.8 排版无障碍
css
/* ✅ Accessible base typography */
html {
font-size: 100%; /* Don't fix to px — respects user browser setting */
}
body {
font-size: 1rem; /* = 16px by default */
line-height: 1.5; /* Readable line spacing */
max-width: 75ch; /* Limit line length for readability */
font-family: /* Choose a readable, designed typeface */;
}
/* ✅ Allow text spacing override (WCAG 1.4.12) */
* {
line-height: inherit !important; /* only in text-spacing tests */
letter-spacing: inherit !important;
word-spacing: inherit !important;
}
/* ✅ Respect zoom — use relative units */
h1 { font-size: clamp(1.5rem, 4vw, 2.5rem); }
p { font-size: clamp(1rem, 1.2vw, 1.125rem); }| Guideline | Minimum | Recommended |
|---|---|---|
| Body text size | 14px (0.875rem) | 16px (1rem) |
| Line height | 1.4 | 1.5–1.6 |
| Max line length | — | 65–75 characters |
| Letter spacing | — | 0 to +0.05em |
| Paragraph spacing | — | 1.5× font-size |
Font selection for accessibility:
- Choose typefaces with clear letterform differentiation (b/d/p/q distinction)
- Avoid decorative fonts for body text
- Avoid light weights (< 300) at small sizes
- Ensure sufficient x-height for readability
css
/* ✅ Accessible base typography */
html {
font-size: 100%; /* Don't fix to px — respects user browser setting */
}
body {
font-size: 1rem; /* = 16px by default */
line-height: 1.5; /* Readable line spacing */
max-width: 75ch; /* Limit line length for readability */
font-family: /* Choose a readable, designed typeface */;
}
/* ✅ Allow text spacing override (WCAG 1.4.12) */
* {
line-height: inherit !important; /* only in text-spacing tests */
letter-spacing: inherit !important;
word-spacing: inherit !important;
}
/* ✅ Respect zoom — use relative units */
h1 { font-size: clamp(1.5rem, 4vw, 2.5rem); }
p { font-size: clamp(1rem, 1.2vw, 1.125rem); }| 指导原则 | 最低要求 | 推荐值 |
|---|---|---|
| 正文文本大小 | 14px (0.875rem) | 16px (1rem) |
| 行高 | 1.4 | 1.5–1.6 |
| 最大行长度 | — | 65–75字符 |
| 字间距 | — | 0到+0.05em |
| 段落间距 | — | 1.5倍字体大小 |
无障碍字体选择:
- 选择字母形态区分度高的字体(b/d/p/q易区分)
- 正文避免使用装饰性字体
- 小字号避免使用字重<300的细体
- 确保足够的x高度以提升可读性
5.9 Motion and Animation
5.9 动效和动画
css
/* ✅ Respect prefers-reduced-motion — implement always */
@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;
}
}
/* ✅ Progressive enhancement pattern */
.card { /* base — no motion */ }
@media (prefers-reduced-motion: no-preference) {
.card {
transition: transform 0.2s ease, box-shadow 0.2s ease;
}
.card:hover {
transform: translateY(-4px);
box-shadow: 0 8px 24px rgba(0,0,0,0.12);
}
}Motion rules:
- Never autoplay videos with motion — use
prefers-reduced-motion - Flashing content: max 3 flashes/second (WCAG 2.3.1)
- Parallax, full-page scroll jacking → provide alternative
prefers-reduced-motion: reduce - Loading spinners are acceptable; full-page animated transitions are not without alternative
css
/* ✅ Respect prefers-reduced-motion — implement always */
@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;
}
}
/* ✅ Progressive enhancement pattern */
.card { /* base — no motion */ }
@media (prefers-reduced-motion: no-preference) {
.card {
transition: transform 0.2s ease, box-shadow 0.2s ease;
}
.card:hover {
transform: translateY(-4px);
box-shadow: 0 8px 24px rgba(0,0,0,0.12);
}
}动效规则:
- 永远不要自动播放带动效的视频——使用适配
prefers-reduced-motion - 闪烁内容:最多每秒闪烁3次(符合WCAG 2.3.1)
- 视差、整页滚动劫持→提供替代方案
prefers-reduced-motion: reduce - 加载动画可接受;整页动画过渡没有替代方案则不可用
5.10 Responsive and Mobile Accessibility
5.10 响应式和移动端无障碍
css
/* ✅ WCAG 1.4.10 Reflow — no horizontal scroll at 320px */
@media (max-width: 320px) {
.container { width: 100%; padding: 0 1rem; }
table { display: block; overflow-x: auto; }
}
/* ✅ WCAG 2.5.8 Minimum target size — 24×24px with spacing */
button, a, [role="button"] {
min-height: 44px; /* Meet WCAG 2.5.5 AAA for comfort */
min-width: 44px;
padding: 0.5rem 1rem;
}
/* ✅ Ensure focus remains visible at all sizes */
:focus-visible {
outline: 2px solid currentColor;
outline-offset: 3px;
}Mobile-specific considerations:
- Use appropriate attributes:
type,type="email",type="tel"type="number" - Don't disable zoom: — NEVER add
<meta name="viewport" content="width=device-width, initial-scale=1">user-scalable=no - Test with VoiceOver (iOS) and TalkBack (Android)
- Avoid hover-only interactions (no hover on touch devices)
- attribute for numeric, decimal, tel, email, url, search inputs
inputmode
css
/* ✅ WCAG 1.4.10 Reflow — no horizontal scroll at 320px */
@media (max-width: 320px) {
.container { width: 100%; padding: 0 1rem; }
table { display: block; overflow-x: auto; }
}
/* ✅ WCAG 2.5.8 Minimum target size — 24×24px with spacing */
button, a, [role="button"] {
min-height: 44px; /* Meet WCAG 2.5.5 AAA for comfort */
min-width: 44px;
padding: 0.5rem 1rem;
}
/* ✅ Ensure focus remains visible at all sizes */
:focus-visible {
outline: 2px solid currentColor;
outline-offset: 3px;
}移动端专属注意事项:
- 使用合适的属性:
type、type="email"、type="tel"type="number" - 不要禁用缩放:——永远不要添加
<meta name="viewport" content="width=device-width, initial-scale=1">user-scalable=no - 使用VoiceOver(iOS)和TalkBack(Android)测试
- 避免仅悬停生效的交互(触摸设备没有悬停)
- 为数字、小数、电话、邮箱、链接、搜索输入添加属性
inputmode
5.11 Tables
5.11 表格
html
<!-- ✅ Accessible data table -->
<table>
<caption>Q4 2024 Sales by Region</caption>
<thead>
<tr>
<th scope="col">Region</th>
<th scope="col">Sales (USD)</th>
<th scope="col">Growth</th>
</tr>
</thead>
<tbody>
<tr>
<th scope="row">North America</th>
<td>$1,240,000</td>
<td>+12%</td>
</tr>
</tbody>
<tfoot>
<tr>
<th scope="row">Total</th>
<td>$3,890,000</td>
<td>+8%</td>
</tr>
</tfoot>
</table>Rules:
- Use to title every table
<caption> - Use for all header cells
<th scope="col|row|colgroup|rowgroup"> - Use ,
<thead>,<tbody>for structure<tfoot> - Don't use tables for layout; use CSS Grid/Flexbox instead
html
<!-- ✅ Accessible data table -->
<table>
<caption>Q4 2024 Sales by Region</caption>
<thead>
<tr>
<th scope="col">Region</th>
<th scope="col">Sales (USD)</th>
<th scope="col">Growth</th>
</tr>
</thead>
<tbody>
<tr>
<th scope="row">North America</th>
<td>$1,240,000</td>
<td>+12%</td>
</tr>
</tbody>
<tfoot>
<tr>
<th scope="row">Total</th>
<td>$3,890,000</td>
<td>+8%</td>
</tr>
</tfoot>
</table>规则:
- 每个表格使用添加标题
<caption> - 所有表头单元格使用
<th scope="col|row|colgroup|rowgroup"> - 使用、
<thead>、<tbody>组织结构<tfoot> - 不要使用表格做布局;改用CSS Grid/Flexbox
Part 6 — Design with Accessibility: Frontend Aesthetic Guidelines
第6部分 — 无障碍设计:前端美学指南
6.1 Design Thinking for Accessible Interfaces
6.1 无障碍界面的设计思维
Before coding, commit to a bold, intentional aesthetic direction while planning for accessibility:
- Purpose: What problem does this solve? Who uses it? What disabilities might users have?
- Tone: Choose an aesthetic extreme: brutally minimal, maximalist typographic, organic/natural, editorial, brutalist, retro-futuristic, luxury/refined, playful, industrial, etc.
- Constraints: Framework, performance, WCAG level (target AA), contrast requirements
- Differentiation: What makes this unforgettable AND accessible? Bold design and WCAG are compatible.
Accessibility informs design, it doesn't constrain it. The best accessible designs use:
- Strong color contrast as a design feature, not a liability
- Clear typographic hierarchy as a visual system
- Visible focus states as intentional design elements
- Semantic structure as compositional logic
编码前,在规划无障碍方案的同时确定鲜明、明确的美学方向:
- 目标:该界面解决什么问题?目标用户是谁?用户可能有哪些障碍?
- 风格:选择明确的美学方向:极简主义、最大化排版、有机自然风、编辑风格、粗野主义、复古未来主义、轻奢精致风、活泼风、工业风等。
- 约束:框架、性能、WCAG等级(目标AA)、对比度要求
- 差异化:什么让这个界面令人难忘同时具备无障碍能力?大胆的设计和WCAG是兼容的。
无障碍赋能设计,而非限制设计。优秀的无障碍设计会用到:
- 高对比度作为设计特色,而非负担
- 清晰的排版层级作为视觉系统
- 可见的焦点状态作为有意的设计元素
- 语义结构作为布局逻辑
6.2 Color System Design for Accessibility
6.2 无障碍色彩系统设计
Design accessible color systems:
css
:root {
/* Accessible palette using HSL for easier contrast calculation */
--color-bg: hsl(220, 15%, 10%); /* Near-black background */
--color-surface: hsl(220, 12%, 15%); /* Elevated surface */
--color-border: hsl(220, 10%, 25%); /* Subtle border */
--color-text-primary: hsl(220, 10%, 95%); /* High contrast text: >7:1 */
--color-text-secondary: hsl(220, 8%, 70%); /* Medium contrast: ~4.5:1 */
--color-text-muted: hsl(220, 6%, 55%); /* Low contrast: ~3:1 (large text only) */
--color-accent: hsl(210, 100%, 65%); /* Action color: verify contrast */
--color-accent-hover: hsl(210, 100%, 72%); /* Hover state */
--color-error: hsl(0, 80%, 65%); /* Error — verify 4.5:1 on bg */
--color-success: hsl(145, 60%, 55%); /* Success — verify 4.5:1 on bg */
--color-warning: hsl(45, 90%, 55%); /* Warning — verify 4.5:1 on bg */
/* Focus ring — must contrast 3:1 with adjacent colors (WCAG 2.4.7) */
--color-focus: hsl(210, 100%, 65%);
--focus-ring: 0 0 0 3px var(--color-focus);
}
/* ✅ Color-scheme support */
@media (prefers-color-scheme: light) {
:root {
--color-bg: hsl(0, 0%, 99%);
--color-text-primary: hsl(220, 20%, 8%);
/* ... recalculate all contrasts */
}
}Multi-modal communication (never color alone):
css
/* ❌ Color only for error */
.input-error { border-color: red; }
/* ✅ Color + icon + text + pattern */
.input-error {
border-color: var(--color-error);
border-width: 2px;
background-image: url("error-icon.svg");
background-position: right 12px center;
background-repeat: no-repeat;
padding-right: 40px;
}设计无障碍色彩系统:
css
:root {
/* Accessible palette using HSL for easier contrast calculation */
--color-bg: hsl(220, 15%, 10%); /* Near-black background */
--color-surface: hsl(220, 12%, 15%); /* Elevated surface */
--color-border: hsl(220, 10%, 25%); /* Subtle border */
--color-text-primary: hsl(220, 10%, 95%); /* High contrast text: >7:1 */
--color-text-secondary: hsl(220, 8%, 70%); /* Medium contrast: ~4.5:1 */
--color-text-muted: hsl(220, 6%, 55%); /* Low contrast: ~3:1 (large text only) */
--color-accent: hsl(210, 100%, 65%); /* Action color: verify contrast */
--color-accent-hover: hsl(210, 100%, 72%); /* Hover state */
--color-error: hsl(0, 80%, 65%); /* Error — verify 4.5:1 on bg */
--color-success: hsl(145, 60%, 55%); /* Success — verify 4.5:1 on bg */
--color-warning: hsl(45, 90%, 55%); /* Warning — verify 4.5:1 on bg */
/* Focus ring — must contrast 3:1 with adjacent colors (WCAG 2.4.7) */
--color-focus: hsl(210, 100%, 65%);
--focus-ring: 0 0 0 3px var(--color-focus);
}
/* ✅ Color-scheme support */
@media (prefers-color-scheme: light) {
:root {
--color-bg: hsl(0, 0%, 99%);
--color-text-primary: hsl(220, 20%, 8%);
/* ... recalculate all contrasts */
}
}多模态信息传递(永远不要仅用颜色传递信息):
css
/* ❌ Color only for error */
.input-error { border-color: red; }
/* ✅ Color + icon + text + pattern */
.input-error {
border-color: var(--color-error);
border-width: 2px;
background-image: url("error-icon.svg");
background-position: right 12px center;
background-repeat: no-repeat;
padding-right: 40px;
}6.3 Typography Design System
6.3 排版设计系统
css
/* ✅ Accessible, distinctive type scale */
:root {
/* Scale: Major Third (1.25) or Perfect Fourth (1.333) */
--text-xs: 0.75rem; /* 12px — captions, labels */
--text-sm: 0.875rem; /* 14px — secondary text */
--text-base: 1rem; /* 16px — body */
--text-lg: 1.125rem; /* 18px — lead text */
--text-xl: 1.25rem; /* 20px */
--text-2xl: 1.5rem; /* 24px */
--text-3xl: 1.875rem; /* 30px */
--text-4xl: 2.25rem; /* 36px */
--text-5xl: 3rem; /* 48px */
--text-6xl: 3.75rem; /* 60px */
/* Accessible line heights */
--leading-tight: 1.25;
--leading-snug: 1.375;
--leading-normal: 1.5;
--leading-relaxed:1.625;
--leading-loose: 2;
/* Weights */
--font-light: 300; /* Use sparingly, large sizes only */
--font-normal: 400;
--font-medium: 500;
--font-semibold: 600;
--font-bold: 700;
--font-black: 900;
}Font selection for accessible uniqueness:
- Avoid Inter, Roboto, Arial, system-ui for display — too generic
- Choose typefaces with strong optical size range: DM Sans, Fraunces, Bricolage Grotesque, Playfair Display, Syne, General Sans, Cabinet Grotesk, Instrument Serif
- Pair distinctive display fonts with clean, readable body fonts
- Verify chosen fonts render legibly at body sizes (14–18px)
- Always have a readable fallback stack
css
/* ✅ Accessible, distinctive type scale */
:root {
/* Scale: Major Third (1.25) or Perfect Fourth (1.333) */
--text-xs: 0.75rem; /* 12px — captions, labels */
--text-sm: 0.875rem; /* 14px — secondary text */
--text-base: 1rem; /* 16px — body */
--text-lg: 1.125rem; /* 18px — lead text */
--text-xl: 1.25rem; /* 20px */
--text-2xl: 1.5rem; /* 24px */
--text-3xl: 1.875rem; /* 30px */
--text-4xl: 2.25rem; /* 36px */
--text-5xl: 3rem; /* 48px */
--text-6xl: 3.75rem; /* 60px */
/* Accessible line heights */
--leading-tight: 1.25;
--leading-snug: 1.375;
--leading-normal: 1.5;
--leading-relaxed:1.625;
--leading-loose: 2;
/* Weights */
--font-light: 300; /* Use sparingly, large sizes only */
--font-normal: 400;
--font-medium: 500;
--font-semibold: 600;
--font-bold: 700;
--font-black: 900;
}独特且无障碍的字体选择:
- 展示字体避免使用Inter、Roboto、Arial、system-ui——过于通用
- 选择光学大小范围广的字体:DM Sans、Fraunces、Bricolage Grotesque、Playfair Display、Syne、General Sans、Cabinet Grotesk、Instrument Serif
- 将有特色的展示字体和清晰易读的正文字体搭配
- 验证所选字体在正文字号(14–18px)下的可读性
- 始终提供易读的 fallback 字体栈
6.4 Focus Indicator as Design Element
6.4 焦点指示器作为设计元素
Make focus indicators intentional design features, not afterthoughts:
css
/* Option 1: Solid outline */
:focus-visible {
outline: 3px solid var(--color-accent);
outline-offset: 3px;
border-radius: var(--radius-sm, 4px);
}
/* Option 2: Box shadow (inset for contained elements) */
:focus-visible {
outline: none;
box-shadow: 0 0 0 3px var(--color-bg), 0 0 0 5px var(--color-accent);
}
/* Option 3: High visibility for text links */
a:focus-visible {
outline: none;
background-color: var(--color-accent);
color: var(--color-bg);
text-decoration: none;
border-radius: 2px;
padding: 0 2px;
}
/* Verify contrast: focused vs unfocused → must be ≥3:1 change */让焦点指示器成为有意的设计特色,而非事后补充:
css
/* Option 1: Solid outline */
:focus-visible {
outline: 3px solid var(--color-accent);
outline-offset: 3px;
border-radius: var(--radius-sm, 4px);
}
/* Option 2: Box shadow (inset for contained elements) */
:focus-visible {
outline: none;
box-shadow: 0 0 0 3px var(--color-bg), 0 0 0 5px var(--color-accent);
}
/* Option 3: High visibility for text links */
a:focus-visible {
outline: none;
background-color: var(--color-accent);
color: var(--color-bg);
text-decoration: none;
border-radius: 2px;
padding: 0 2px;
}
/* Verify contrast: focused vs unfocused → must be ≥3:1 change */6.5 Spacing and Layout for Motor Accessibility
6.5 运动无障碍的间距和布局
css
/* ✅ Generous interactive targets */
.btn {
/* Minimum visually 44×44 (WCAG 2.5.5 AAA) */
min-height: 44px;
padding-inline: 1.25rem;
display: inline-flex;
align-items: center;
gap: 0.5rem;
}
/* ✅ Inline links — guaranteed minimum height */
a {
display: inline-block; /* Ensures tap area */
padding: 0.25em 0;
}
/* ✅ Spacing between small targets (WCAG 2.5.8 AA) */
.icon-group { gap: 0.5rem; } /* 8px between 24px targets = sufficient */
/* ✅ Grid and flex for logical order */
/* Visual order must match DOM order for keyboard/screen reader users */
/* Avoid using CSS `order` property to reorder visual layout */css
/* ✅ Generous interactive targets */
.btn {
/* Minimum visually 44×44 (WCAG 2.5.5 AAA) */
min-height: 44px;
padding-inline: 1.25rem;
display: inline-flex;
align-items: center;
gap: 0.5rem;
}
/* ✅ Inline links — guaranteed minimum height */
a {
display: inline-block; /* Ensures tap area */
padding: 0.25em 0;
}
/* ✅ Spacing between small targets (WCAG 2.5.8 AA) */
.icon-group { gap: 0.5rem; } /* 8px between 24px targets = sufficient */
/* ✅ Grid and flex for logical order */
/* Visual order must match DOM order for keyboard/screen reader users */
/* Avoid using CSS `order` property to reorder visual layout */6.6 Accessible Animation Design
6.6 无障碍动画设计
css
/* ✅ Always implement reduced-motion alternative */
:root {
--duration-fast: 150ms;
--duration-base: 250ms;
--duration-slow: 400ms;
--easing-out: cubic-bezier(0.16, 1, 0.3, 1);
}
@media (prefers-reduced-motion: reduce) {
:root {
--duration-fast: 0ms;
--duration-base: 0ms;
--duration-slow: 0ms;
}
}
/* ✅ Purpose-driven micro-interactions */
.btn {
transition:
background-color var(--duration-fast) ease,
transform var(--duration-fast) var(--easing-out),
box-shadow var(--duration-fast) ease;
}
.btn:hover {
transform: translateY(-1px);
box-shadow: 0 4px 12px rgba(0,0,0,0.15);
}
.btn:active {
transform: translateY(0);
box-shadow: none;
}css
/* ✅ Always implement reduced-motion alternative */
:root {
--duration-fast: 150ms;
--duration-base: 250ms;
--duration-slow: 400ms;
--easing-out: cubic-bezier(0.16, 1, 0.3, 1);
}
@media (prefers-reduced-motion: reduce) {
:root {
--duration-fast: 0ms;
--duration-base: 0ms;
--duration-slow: 0ms;
}
}
/* ✅ Purpose-driven micro-interactions */
.btn {
transition:
background-color var(--duration-fast) ease,
transform var(--duration-fast) var(--easing-out),
box-shadow var(--duration-fast) ease;
}
.btn:hover {
transform: translateY(-1px);
box-shadow: 0 4px 12px rgba(0,0,0,0.15);
}
.btn:active {
transform: translateY(0);
box-shadow: none;
}Part 7 — Testing Checklist
第7部分 — 测试清单
Quick Audit (5 minutes)
快速审核(5分钟)
- Tab through entire page — can you reach and activate everything?
- Focus indicator visible at all times?
- Check color contrast with browser DevTools
- Run axe DevTools or Lighthouse accessibility audit
- Check page without CSS (semantic structure visible?)
- 按Tab遍历整个页面——你能访问并触发所有功能吗?
- 焦点指示器始终可见吗?
- 用浏览器DevTools检查颜色对比度
- 运行axe DevTools或Lighthouse无障碍审计
- 禁用CSS查看页面——语义结构清晰可见吗?
Standard Audit (WCAG 2.2 AA)
标准审计(WCAG 2.2 AA)
Perceivable
- All images have meaningful alt text (or for decorative)
alt="" - Color contrast ≥4.5:1 normal text, ≥3:1 large text and UI elements
- Color not the only way to convey information
- Content readable/functional at 200% zoom
- No horizontal scroll at 320px wide (reflow)
- Text spacing overrides don't break layout
- No auto-playing audio without controls
Operable
- All functionality keyboard-accessible
- No keyboard traps
- Focus indicator always visible
- Focus not obscured by sticky headers/footers
- Skip navigation link present
- All pages have descriptive
<title> - Focus order is logical
- Links have clear, descriptive text
- Touch targets ≥24×24px with adequate spacing
- No content flashes >3×/second
Understandable
- set correctly
<html lang="en"> - Language changes marked with attribute
lang - No unexpected context changes on focus
- Navigation consistent across pages
- All form inputs have visible labels
- Errors identified, described, and suggestions offered
- Help mechanism in consistent location
Robust
- All form controls have name, role, value via HTML or ARIA
- Status messages announced without focus change
- Valid, well-structured HTML (no broken nesting)
- ARIA roles/states used correctly
- Dynamic content updates announced
可感知
- 所有图片都有有意义的alt文本(装饰性图片为)
alt="" - 普通文本对比度≥4.5:1,大文本和UI元素对比度≥3:1
- 颜色不是传达信息的唯一方式
- 200%缩放时内容可读/功能正常
- 320px宽度时无横向滚动(重排要求)
- 文本间距覆盖不会破坏布局
- 无自动播放且无控制选项的音频
可操作
- 所有功能都支持键盘访问
- 无键盘陷阱
- 焦点指示器始终可见
- 焦点不会被粘性头部/底部遮挡
- 存在跳过导航链接
- 所有页面都有描述性的
<title> - 焦点顺序逻辑合理
- 链接有清晰的描述性文本
- 触摸目标≥24×24px且有足够间距
- 无每秒闪烁超过3次的内容
可理解
- 正确设置
<html lang="en"> - 语言变化用属性标记
lang - 获得焦点时不会触发意外的上下文变化
- 不同页面的导航逻辑一致
- 所有表单输入都有可见标签
- 错误会被识别、描述并提供修正建议
- 帮助机制在不同页面的位置一致
健壮性
- 所有表单控件通过HTML或ARIA提供名称、角色、值
- 状态消息无需焦点变化即可被播报
- HTML有效、结构良好(无嵌套错误)
- ARIA角色/状态使用正确
- 动态内容更新会被播报
Screen Reader Testing
屏幕阅读器测试
Test with: NVDA + Chrome (Windows), VoiceOver + Safari (Mac), TalkBack + Chrome (Android)
- Heading structure navigable and logical
- Landmarks navigable (nav, main, aside, footer)
- Form labels read correctly
- Error messages announced when fields are invalid
- Dynamic content (alerts, status) announced
- Modals: focus traps, Escape closes, focus returns
测试工具:NVDA + Chrome(Windows)、VoiceOver + Safari(Mac)、TalkBack + Chrome(Android)
- 标题结构可导航且逻辑合理
- 地标可导航(nav、main、aside、footer)
- 表单标签可正确朗读
- 字段无效时会播报错误消息
- 动态内容(提醒、状态)会被播报
- 模态框:焦点陷阱正常、Escape可关闭、关闭后焦点返回
Part 8 — Legal and Standards Context
第8部分 — 法律和标准背景
| Standard | Jurisdiction | Based On |
|---|---|---|
| ADA (Americans with Disabilities Act) | USA | WCAG 2.1 AA |
| Section 508 | USA (Federal) | WCAG 2.0 AA |
| EN 301 549 | European Union | WCAG 2.1 AA |
| AODA | Ontario, Canada | WCAG 2.0 AA |
| Equality Act 2010 | UK | WCAG 2.1 AA |
| BS 8878 | UK | WCAG 2.1 |
| BITV 2.0 | Germany | WCAG 2.1 AA |
Recommended target: WCAG 2.2 AA — exceeds requirements of all major laws and is future-proof.
| 标准 | 适用地区 | 基于标准 |
|---|---|---|
| ADA(美国残疾人法案) | 美国 | WCAG 2.1 AA |
| Section 508 | 美国(联邦机构) | WCAG 2.0 AA |
| EN 301 549 | 欧盟 | WCAG 2.1 AA |
| AODA | 加拿大安大略省 | WCAG 2.0 AA |
| 2010年平等法案 | 英国 | WCAG 2.1 AA |
| BS 8878 | 英国 | WCAG 2.1 |
| BITV 2.0 | 德国 | WCAG 2.1 AA |
推荐目标:WCAG 2.2 AA——超过所有主流法律的要求,且面向未来。
Part 9 — Tools and Resources
第9部分 — 工具和资源
Testing Tools
测试工具
| Tool | Type | Use For |
|---|---|---|
| axe DevTools | Browser extension + CI | Most comprehensive automated checks |
| WAVE (WebAIM) | Browser extension | Visual error overlay |
| Lighthouse | Chrome DevTools | Quick baseline audit |
| Colour Contrast Analyser | Desktop app | Pixel-accurate contrast check |
| WebAIM Contrast Checker | Web tool | Quick contrast calculation |
| NVDA | Screen reader | Windows screen reader testing (free) |
| VoiceOver | Screen reader | Mac/iOS built-in |
| TalkBack | Screen reader | Android built-in |
| Keyboard | Manual | Always test keyboard-only navigation |
| 工具 | 类型 | 用途 |
|---|---|---|
| axe DevTools | 浏览器扩展 + CI | 最全面的自动化检查工具 |
| WAVE(WebAIM) | 浏览器扩展 | 可视化错误覆盖 |
| Lighthouse | Chrome DevTools | 快速基线审计 |
| 颜色对比度分析器 | 桌面应用 | 像素级精确的对比度检查 |
| WebAIM对比度检查器 | Web工具 | 快速对比度计算 |
| NVDA | 屏幕阅读器 | Windows屏幕阅读器测试(免费) |
| VoiceOver | 屏幕阅读器 | Mac/iOS内置 |
| TalkBack | 屏幕阅读器 | Android内置 |
| 键盘 | 手动测试 | 始终测试纯键盘导航 |
Key References
核心参考资料
- WCAG 2.2 Specification: https://www.w3.org/TR/WCAG22/
- WAI-ARIA Authoring Practices Guide: https://www.w3.org/WAI/ARIA/apg/
- WebAIM Articles: https://webaim.org/articles/
- The A11Y Project: https://www.a11yproject.com/
- Deque University: https://dequeuniversity.com/
- MDN Accessibility: https://developer.mozilla.org/en-US/docs/Web/Accessibility
- Inclusive Components (Heydon Pickering): https://inclusive-components.design/
- A11y Coffee: https://a11y.coffee/
- WCAG 2.2规范: https://www.w3.org/TR/WCAG22/
- WAI-ARIA创作实践指南: https://www.w3.org/WAI/ARIA/apg/
- WebAIM文章: https://webaim.org/articles/
- The A11Y Project: https://www.a11yproject.com/
- Deque University: https://dequeuniversity.com/
- MDN无障碍指南: https://developer.mozilla.org/en-US/docs/Web/Accessibility
- Inclusive Components(Heydon Pickering): https://inclusive-components.design/
- A11y Coffee: https://a11y.coffee/
Summary: Non-Negotiable AA Rules
总结:必须遵守的AA规则
When building any frontend interface, these WCAG 2.2 AA rules are always required:
- Contrast: 4.5:1 normal text, 3:1 large text and UI components
- Alt text: Every informative image has descriptive alt; decorative has
alt="" - Keyboard: 100% of functionality reachable and operable via keyboard alone
- Focus visible: Visible focus indicator that is never removed
- Labels: Every form input has an associated visible
<label> - Errors: Errors identified in text, not color alone; aria-invalid used; suggestions provided
- Headings: Logical hierarchy, no skipped levels
- Language: always set
<html lang="..."> - Semantic HTML: Use ,
<button>,<a>,<nav>etc., not<main>substitutes<div> - No color-only info: Never use color as the sole means to convey any information
- Reflow: Content usable at 320px width without horizontal scrolling
- Touch targets: Interactive elements ≥24×24px or adequate spacing
- Focus not obscured: Sticky headers/footers don't hide focused elements
- Status messages: Dynamic status/error messages announced to screen readers
- Consistent help: Help mechanisms in the same location across pages
构建任何前端界面时,以下WCAG 2.2 AA规则是强制要求的:
- 对比度:普通文本4.5:1,大文本和UI组件3:1
- Alt文本:每个信息类图片都有描述性alt;装饰性图片为
alt="" - 键盘可访问:100%的功能都可以仅通过键盘访问和操作
- 焦点可见:永远不要移除可见的焦点指示器
- 标签:每个表单输入都有关联的可见
<label> - 错误处理:错误以文本形式标识,而非仅用颜色;使用aria-invalid;提供修正建议
- 标题:逻辑层级,不跳过等级
- 语言:始终设置
<html lang="..."> - 语义化HTML:使用、
<button>、<a>、<nav>等元素,而非<main>替代<div> - 不只用颜色传递信息:永远不要将颜色作为传达任何信息的唯一手段
- 重排:320px宽度时内容可用,无需横向滚动
- 触摸目标:交互元素≥24×24px或有足够间距
- 焦点不被遮挡:粘性头部/底部不会隐藏聚焦元素
- 状态消息:动态状态/错误消息会被屏幕阅读器播报
- 一致的帮助:帮助机制在不同页面的位置一致