wcag-design

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

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

版本历史

VersionYearNotes
WCAG 1.01999First W3C accessibility recommendation
WCAG 2.02008Major restructure with testable success criteria
WCAG 2.12018+17 new criteria for mobile, low vision, cognitive
WCAG 2.22023+9 new criteria, removed 4.1.1 Parsing; current standard
WCAG 3.0~2028Draft; plain language, outcome-oriented model
Backward compatibility: Content conforming to WCAG 2.2 also conforms to 2.1 and 2.0.

版本年份备注
WCAG 1.01999首个W3C无障碍推荐标准
WCAG 2.02008重大重构,引入可测试的成功标准
WCAG 2.12018新增17项针对移动端、低视力、认知障碍的标准
WCAG 2.22023新增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部分 — 合规等级

LevelCriteria CountDescription
A32Minimum — 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.).

等级标准数量说明
A32最低等级——基础无障碍能力,合规的基石
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 — 文本替代方案

CriterionLevelRule
1.1.1 Non-text ContentAAll non-text content has a text alternative (images, icons, charts, buttons)
标准等级规则
1.1.1 非文本内容A所有非文本内容(图片、图标、图表、按钮)都要有文本替代说明

Guideline 1.2 — Time-based Media

指南1.2 — 时基媒体

CriterionLevelRule
1.2.1 Audio-only and Video-only (Prerecorded)AProvide transcript or audio description
1.2.2 Captions (Prerecorded)ACaptions for all prerecorded audio in multimedia
1.2.3 Audio Description or Media Alternative (Prerecorded)AProvide audio description or full text alternative
1.2.4 Captions (Live)AACaptions for all live multimedia
1.2.5 Audio Description (Prerecorded)AAAudio description for all prerecorded video
1.2.6 Sign Language (Prerecorded)AAASign language interpretation for prerecorded audio
1.2.7 Extended Audio Description (Prerecorded)AAAExtended audio description where pauses are insufficient
1.2.8 Media Alternative (Prerecorded)AAAFull text alternative for all prerecorded media
1.2.9 Audio-only (Live)AAAAlternative 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 — 可适配

CriterionLevelRule
1.3.1 Info and RelationshipsAStructure and relationships conveyed through presentation must be programmatically determinable
1.3.2 Meaningful SequenceAReading and navigation order is logical
1.3.3 Sensory CharacteristicsAInstructions don't rely solely on color, size, shape, visual location, or sound
1.3.4 OrientationAAContent not restricted to portrait or landscape orientation
1.3.5 Identify Input PurposeAAInput fields have programmatically identified purpose (autocomplete)
1.3.6 Identify PurposeAAAPurpose 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 — 可区分

CriterionLevelRule
1.4.1 Use of ColorAColor is not the only visual means of conveying information
1.4.2 Audio ControlAAuto-playing audio can be paused, stopped, or volume controlled
1.4.3 Contrast (Minimum)AA4.5:1 for normal text; 3:1 for large text
1.4.4 Resize TextAAText can be resized to 200% without loss of content
1.4.5 Images of TextAAUse actual text instead of images of text where possible
1.4.6 Contrast (Enhanced)AAA7:1 for normal text; 4.5:1 for large text
1.4.7 Low or No Background AudioAAAAudio-only content clearly audible over background
1.4.8 Visual PresentationAAAText width limited, line spacing adjustable, no full justification
1.4.9 Images of Text (No Exception)AAANo images of text except logos
1.4.10 ReflowAAContent presentable without horizontal scrolling at 320px wide
1.4.11 Non-text ContrastAAUI components and graphical elements have 3:1 contrast ratio
1.4.12 Text SpacingAANo loss of content when line height ≥1.5×, spacing ≥0.12em, word spacing ≥0.16em
1.4.13 Content on Hover or FocusAAHoverable/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 非文本对比度AAUI组件和图形元素的对比度≥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 — 键盘可访问

CriterionLevelRule
2.1.1 KeyboardAAll functionality operable via keyboard
2.1.2 No Keyboard TrapAUser can navigate away from any component using keyboard
2.1.3 Keyboard (No Exception)AAAAll functionality operable via keyboard — no exceptions
2.1.4 Character Key ShortcutsASingle-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 — 充足时间

CriterionLevelRule
2.2.1 Timing AdjustableATime limits can be turned off, adjusted, or extended (≥10× default)
2.2.2 Pause, Stop, HideAAuto-moving/blinking/scrolling content can be paused, stopped, or hidden
2.2.3 No TimingAAANo time restrictions except for real-time events
2.2.4 InterruptionsAAAUser can postpone or suppress all interruptions
2.2.5 Re-authenticatingAAANo data lost when re-authenticating after timeout
2.2.6 TimeoutsAAAUsers 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 — 癫痫和身体反应

CriterionLevelRule
2.3.1 Three Flashes or Below ThresholdANo flashing content more than 3 times/second (or below threshold)
2.3.2 Three FlashesAAAAll content restricted to ≤3 flashes/second
2.3.3 Animation from InteractionsAAAMotion 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 — 可导航

CriterionLevelRule
2.4.1 Bypass BlocksAMechanism to skip repeated blocks (skip nav link)
2.4.2 Page TitledAWeb pages have descriptive titles
2.4.3 Focus OrderAFocus order is logical and meaningful
2.4.4 Link Purpose (In Context)ALink purpose clear from link text or context
2.4.5 Multiple WaysAAMultiple ways to locate a page (search, sitemap, navigation)
2.4.6 Headings and LabelsAAHeadings and labels describe topic or purpose
2.4.7 Focus VisibleAAKeyboard focus indicator is visible
2.4.8 LocationAAAUser knows their location within a set of pages
2.4.9 Link Purpose (Link Only)AAALink purpose clear from link text alone
2.4.10 Section HeadingsAAASection headings organize content
2.4.11 Focus Not Obscured (Minimum) ⭐ NEW 2.2AAFocused element not entirely hidden by sticky/fixed content
2.4.12 Focus Not Obscured (Enhanced) ⭐ NEW 2.2AAAFocused element fully visible
2.4.13 Focus Appearance ⭐ NEW 2.2AAAFocus 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 — 输入模态

CriterionLevelRule
2.5.1 Pointer GesturesAPath-based gestures have single-pointer alternative
2.5.2 Pointer CancellationAPointer actions activate on "up" event, not "down"
2.5.3 Label in NameAAccessible name contains the visible label text
2.5.4 Motion ActuationAMotion-triggered functions have UI alternative and can be disabled
2.5.5 Target Size (Enhanced)AAATouch targets ≥44×44 CSS pixels
2.5.6 Concurrent Input MechanismsAAANo restriction on input modality
2.5.7 Dragging Movements ⭐ NEW 2.2AADrag-only functionality has single-pointer alternative
2.5.8 Target Size (Minimum) ⭐ NEW 2.2AATouch 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 — 可读

CriterionLevelRule
3.1.1 Language of PageADefault human language programmatically identified (lang attribute)
3.1.2 Language of PartsAALanguage changes in content are marked
3.1.3 Unusual WordsAAADefinitions for jargon, idioms, technical terms
3.1.4 AbbreviationsAAAAbbreviations expanded on first use
3.1.5 Reading LevelAAAText at lower secondary education level or simplified version available
3.1.6 PronunciationAAAPronunciation 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 — 可预测

CriterionLevelRule
3.2.1 On FocusANo context change when component receives focus
3.2.2 On InputAChanging settings doesn't automatically submit form
3.2.3 Consistent NavigationAANavigation mechanisms in same relative order across pages
3.2.4 Consistent IdentificationAAComponents with same function identified consistently
3.2.5 Change on RequestAAAContext changes only at user request
3.2.6 Consistent Help ⭐ NEW 2.2AHelp 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 — 输入辅助

CriterionLevelRule
3.3.1 Error IdentificationAErrors identified and described in text
3.3.2 Labels or InstructionsALabels or instructions provided for all inputs
3.3.3 Error SuggestionAASuggestions provided for input errors where known
3.3.4 Error Prevention (Legal, Financial, Data)AACritical submissions are reversible, checked, or confirmed
3.3.5 HelpAAAContext-sensitive help available
3.3.6 Error Prevention (All)AAAAll inputs can be reversed, checked, or confirmed
3.3.7 Redundant Entry ⭐ NEW 2.2APreviously entered info not required again in same session
3.3.8 Accessible Authentication (Minimum) ⭐ NEW 2.2AAAuthentication without cognitive function test or memory requirement
3.3.9 Accessible Authentication (Enhanced) ⭐ NEW 2.2AAAEnhanced 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 — 兼容性

CriterionLevelRule
4.1.1 ParsingARemoved in WCAG 2.2 — obsolete due to HTML5 error correction
4.1.2 Name, Role, ValueAAll components have accessible name, role, and state/value
4.1.3 Status MessagesAAStatus messages announced to screen readers without focus change

标准等级规则
4.1.1 解析AWCAG 2.2已移除——因HTML5错误纠正机制已过时
4.1.2 名称、角色、值A所有组件都有可访问的名称、角色和状态/值
4.1.3 状态消息AA状态消息无需焦点变化即可被屏幕阅读器播报

Part 5 — Implementation Reference

第5部分 — 实现参考

5.1 Color Contrast Rules

5.1 颜色对比度规则

ContextAA MinimumAAA Enhanced
Normal text (<18px or <14px bold)4.5:17:1
Large text (≥18px or ≥14px bold)3:14.5:1
UI components & graphics3:13:1
Placeholder text4.5:1
Disabled elementsExemptExempt
Decorative elementsExemptExempt
Dark Mode Note: Dark themes must still meet contrast ratios. Avoid pure black
#000000
(causes halation/eye strain); use soft blacks like
#0f0f0f
or
#121212
. High-saturation colors on dark backgrounds may vibrate visually — reduce saturation.
Tools: WebAIM Contrast Checker, Colour Contrast Analyser, axe DevTools, Chrome DevTools.

场景AA最低要求AAA增强要求
普通文本(<18px或<14px粗体)4.5:17:1
大文本(≥18px或≥14px粗体)3:14.5:1
UI组件和图形3:13: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:
ElementARIA Landmark Role
<header>
banner
<nav>
navigation
<main>
main
<aside>
complementary
<footer>
contentinfo
<section aria-label="...">
region
<form>
form
Heading hierarchy rule: Never skip levels.
<h1>
<h2>
<h3>
(not h1 → h3). Multiple
<h1>
elements are acceptable but first should be page/section title.

始终优先选择语义化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地标角色
<header>
banner
<nav>
navigation
<main>
main
<aside>
complementary
<footer>
contentinfo
<section aria-label="...">
region
<form>
form
**标题层级规则:**不要跳过层级。按
<h1>
<h2>
<h3>
的顺序使用(不要从h1直接跳到h3)。允许页面存在多个
<h1>
元素,但第一个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

各组件键盘交互模式

ComponentKeyAction
AllTabMove focus forward
AllShift+TabMove focus backward
ButtonEnter / SpaceActivate
LinkEnterFollow link
CheckboxSpaceToggle
Radio GroupArrow KeysSelect option
Select/DropdownArrow KeysNavigate; Enter select
DialogEscapeClose
DialogTabCycle within dialog only
MenuArrow KeysNavigate items
MenuEscapeClose
MenuEnter / SpaceActivate item
SliderArrow KeysIncrement/Decrement
SliderHome / EndMin / Max value
TabsArrow KeysSwitch tabs
TreeArrow KeysExpand/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 focus
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 focus

Accessible 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
    blur
    or
    submit
    , not on every keystroke
  • Mark invalid fields with
    aria-invalid="true"
  • Link error messages to fields via
    aria-describedby
  • Use
    role="alert"
    on dynamically inserted error messages
  • 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); }
GuidelineMinimumRecommended
Body text size14px (0.875rem)16px (1rem)
Line height1.41.5–1.6
Max line length65–75 characters
Letter spacing0 to +0.05em
Paragraph spacing1.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.41.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
    prefers-reduced-motion: reduce
    alternative
  • 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
    type
    attributes:
    type="email"
    ,
    type="tel"
    ,
    type="number"
  • Don't disable zoom:
    <meta name="viewport" content="width=device-width, initial-scale=1">
    — NEVER add
    user-scalable=no
  • Test with VoiceOver (iOS) and TalkBack (Android)
  • Avoid hover-only interactions (no hover on touch devices)
  • inputmode
    attribute for numeric, decimal, tel, email, url, search inputs

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
    <caption>
    to title every table
  • Use
    <th scope="col|row|colgroup|rowgroup">
    for all header cells
  • Use
    <thead>
    ,
    <tbody>
    ,
    <tfoot>
    for structure
  • 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
    alt=""
    for decorative)
  • 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
  • <html lang="en">
    set correctly
  • Language changes marked with
    lang
    attribute
  • 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部分 — 法律和标准背景

StandardJurisdictionBased On
ADA (Americans with Disabilities Act)USAWCAG 2.1 AA
Section 508USA (Federal)WCAG 2.0 AA
EN 301 549European UnionWCAG 2.1 AA
AODAOntario, CanadaWCAG 2.0 AA
Equality Act 2010UKWCAG 2.1 AA
BS 8878UKWCAG 2.1
BITV 2.0GermanyWCAG 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

测试工具

ToolTypeUse For
axe DevToolsBrowser extension + CIMost comprehensive automated checks
WAVE (WebAIM)Browser extensionVisual error overlay
LighthouseChrome DevToolsQuick baseline audit
Colour Contrast AnalyserDesktop appPixel-accurate contrast check
WebAIM Contrast CheckerWeb toolQuick contrast calculation
NVDAScreen readerWindows screen reader testing (free)
VoiceOverScreen readerMac/iOS built-in
TalkBackScreen readerAndroid built-in
KeyboardManualAlways test keyboard-only navigation
工具类型用途
axe DevTools浏览器扩展 + CI最全面的自动化检查工具
WAVE(WebAIM)浏览器扩展可视化错误覆盖
LighthouseChrome DevTools快速基线审计
颜色对比度分析器桌面应用像素级精确的对比度检查
WebAIM对比度检查器Web工具快速对比度计算
NVDA屏幕阅读器Windows屏幕阅读器测试(免费)
VoiceOver屏幕阅读器Mac/iOS内置
TalkBack屏幕阅读器Android内置
键盘手动测试始终测试纯键盘导航

Key References

核心参考资料



Summary: Non-Negotiable AA Rules

总结:必须遵守的AA规则

When building any frontend interface, these WCAG 2.2 AA rules are always required:
  1. Contrast: 4.5:1 normal text, 3:1 large text and UI components
  2. Alt text: Every informative image has descriptive alt; decorative has
    alt=""
  3. Keyboard: 100% of functionality reachable and operable via keyboard alone
  4. Focus visible: Visible focus indicator that is never removed
  5. Labels: Every form input has an associated visible
    <label>
  6. Errors: Errors identified in text, not color alone; aria-invalid used; suggestions provided
  7. Headings: Logical hierarchy, no skipped levels
  8. Language:
    <html lang="...">
    always set
  9. Semantic HTML: Use
    <button>
    ,
    <a>
    ,
    <nav>
    ,
    <main>
    etc., not
    <div>
    substitutes
  10. No color-only info: Never use color as the sole means to convey any information
  11. Reflow: Content usable at 320px width without horizontal scrolling
  12. Touch targets: Interactive elements ≥24×24px or adequate spacing
  13. Focus not obscured: Sticky headers/footers don't hide focused elements
  14. Status messages: Dynamic status/error messages announced to screen readers
  15. Consistent help: Help mechanisms in the same location across pages
构建任何前端界面时,以下WCAG 2.2 AA规则是强制要求的:
  1. 对比度:普通文本4.5:1,大文本和UI组件3:1
  2. Alt文本:每个信息类图片都有描述性alt;装饰性图片为
    alt=""
  3. 键盘可访问:100%的功能都可以仅通过键盘访问和操作
  4. 焦点可见:永远不要移除可见的焦点指示器
  5. 标签:每个表单输入都有关联的可见
    <label>
  6. 错误处理:错误以文本形式标识,而非仅用颜色;使用aria-invalid;提供修正建议
  7. 标题:逻辑层级,不跳过等级
  8. 语言:始终设置
    <html lang="...">
  9. 语义化HTML:使用
    <button>
    <a>
    <nav>
    <main>
    等元素,而非
    <div>
    替代
  10. 不只用颜色传递信息:永远不要将颜色作为传达任何信息的唯一手段
  11. 重排:320px宽度时内容可用,无需横向滚动
  12. 触摸目标:交互元素≥24×24px或有足够间距
  13. 焦点不被遮挡:粘性头部/底部不会隐藏聚焦元素
  14. 状态消息:动态状态/错误消息会被屏幕阅读器播报
  15. 一致的帮助:帮助机制在不同页面的位置一致