无障碍 Web 开发:WCAG 标准与 ARIA 实践

FreeGuideOnline 最新 2026-06-12

Web 可访问性 (A11y) 全面指南:从 WCAG 标准到 ARIA 实践

引言:为什么可访问性至关重要

Web 可访问性(常缩写为 A11y,源自“accessibility”首尾字母 a 与 y 之间共 11 个字母)确保残障人士能够感知、理解、导航和与网站交互。这不仅是一种道德责任,还能提升所有用户的体验,并帮助网站符合法律法规(如 ADA、Section 508)。本教程将带你深入理解 WCAG 标准,并学会如何使用 ARIA 构建真正包容的 Web 应用。


一、什么是 Web 内容无障碍指南 (WCAG)

Web 内容无障碍指南(WCAG)是全球公认的 Web 可访问性标准,由 W3C 的 WAI 发布。目前最新稳定版本为 WCAG 2.1WCAG 2.2 也已进入最终推荐阶段。WCAG 基于四大原则构建,通常简写为 POUR

1.1 可感知 (Perceivable)

信息和用户界面组件必须以用户可以感知的方式呈现。

  • 文本替代 (1.1.1):所有非文本内容都需要提供同等的文本替代,如图片的 alt 属性。
  • 基于时间的媒体 (1.2.x):为音频/视频提供字幕、手语翻译、音频描述。
  • 适应性 (1.3.x):内容创建的方式应能在不丢失信息或结构的情况下以不同方式呈现(如屏幕阅读器能理解表单标签与控件的关联)。
  • 可辨别性 (1.4.x):确保前景与背景有足够的颜色对比度,内容可通过颜色之外的方式传达信息。

1.2 可操作 (Operable)

用户界面组件和导航必须可操作。

  • 键盘可访问 (2.1.x):所有功能应能通过键盘完成,无需特定的时间节奏。
  • 充足的时间 (2.2.x):为用户提供充足的时间阅读和使用内容,允许关闭、调整或延长时限。
  • 癫痫和物理反应 (2.3.x):不设计会导致癫痫发作的内容(如每秒闪烁超过 3 次)。
  • 可导航 (2.4.x):提供多种方式帮助用户定位和导航,如 “跳过导航”链接、描述性页面标题、有意义的焦点顺序。
  • 输入模式 (2.5.x):使功能通过除键盘外的各种输入方式更易操作,特别针对触摸和语音识别。

1.3 可理解 (Understandable)

用户界面的信息和操作必须是可理解的。

  • 可读性 (3.1.x):指定页面的主要人类语言,对罕见词汇或缩写提供解释。
  • 可预测性 (3.2.x):让网页以可预测的方式呈现和运行,避免在焦点移动时发生意外的上下文更改。
  • 输入辅助 (3.3.x):帮助用户避免和纠正错误,提供清晰的错误消息、标签和补救建议。

1.4 健壮性 (Robust)

内容必须足够健壮,能够被各种用户代理(包括辅助技术)可靠地解释。

  • 兼容性 (4.1.x):最大化兼容当前和未来的用户代理,尤其是通过正确使用标记语言和 ARIA。

二、符合性等级与遵从性

WCAG 定义了三个符合性等级,每个等级包含一系列成功标准:

  • A 级(最低):满足最基本的无障碍要求。若未达标,某些群体将完全无法访问网站。
  • AA 级(适中):满足更广泛的无障碍需求,大多数全球法律政策的目标等级。例如要求颜色对比度至少达到 4.5:1(正常文本)。
  • AAA 级(最高):最严格的无障碍要求,通常不可能在整站达成所有 AAA 标准,但可针对部分内容应用。

追求 AA 级遵从性是切实可行的起点。

三、构建无障碍 HTML 的基础实践

在引入 ARIA 之前,应优先使用语义化 HTML,因为它天然携带隐式的角色、状态和属性,这是可访问性的基石。

3.1 语义化结构

  • 使用 <header>, <nav>, <main>, <footer> 定义页面区域。
  • <h1><h6> 创建清晰的标题层,不跳过层级。
  • 列表使用 <ul>, <ol>, <dl>;表格使用 <table> 并配合 <caption>, <thead>, <tbody>, <th scope>

3.2 表单与控件

  • 每个输入控件必须有相关联的 <label>。显式关联使用 forid 属性:
    <label for="email">电子邮箱</label>
    <input type="email" id="email" name="email">
    
  • 对必填字段提供视觉提示和 aria-required="true" 属性,但更推荐使用 HTML5 required 属性。
  • 分组相关选项用 <fieldset><legend>

3.3 图像与媒体

  • 信息图片使用描述性 alt 文本;纯装饰性图片使用空 alt="",使其被屏幕阅读器忽略。
  • 复杂图表应提供长文本描述,通过 longdesc 属性或页面内文本链接。
  • 视频始终提供字幕,音频提供文字稿。

3.4 链接与按钮

  • 使用 <a> 实现导航,<button> 触发操作。
  • 链接文本应表达明确目的地,避免“点击这里”、“了解更多”这类含糊描述。
  • 若控件仅为图标,确保有辅助文本(如 aria-label 或隐藏的 <span>)。

四、ARIA 深入实践:何时以及如何使用

ARIA (Accessible Rich Internet Applications) 是一套当原生 HTML 无法提供足够语义时,用于增强可访问性的属性。

4.1 ARIA 的核心组成

  • 角色 (Roles):定义元素是什么。如 role="navigation"role="alert"role="tablist"
  • 属性 (Properties):赋予元素额外意义。如 aria-labelaria-describedby
  • 状态 (States):反映当前状况。如 aria-expanded="true"aria-selected="false"

4.2 关键 ARIA 模式实战

实时区域 (Live Regions) 动态内容更新时,通知辅助技术而不移动焦点。

<div aria-live="polite" aria-atomic="true">
  <!-- 更新购物车数量时,屏幕阅读器会朗读此处内容 -->
</div>

aria-live 值:

  • off:默认,不宣告更新。
  • polite:当用户空闲时宣告。
  • assertive:立即宣告,可能打断当前朗读。

对话框(模态框)管理 一个无障碍的对话框需要同时管理焦点、标签和键盘陷阱。

<div role="dialog" aria-modal="true" aria-labelledby="dialog-title">
  <h2 id="dialog-title">确认删除</h2>
  <!-- 打开对话框时,焦点应移至第一个可聚焦元素或对话框本身 -->
  <!-- 关闭时,焦点应回到触发元素 -->
</div>

关键点:使用 aria-labelledby 为对话框提供名称,用 aria-modal="true" 指示其后的内容被禁用,并通过 JavaScript 实现 Tab 键在对话框内循环。

选项卡 (Tabs)

<div role="tablist" aria-label="产品信息">
  <button role="tab" aria-selected="true" aria-controls="panel1" id="tab1">描述</button>
  <button role="tab" aria-selected="false" aria-controls="panel2" id="tab2">评价</button>
</div>
<div role="tabpanel" id="panel1" aria-labelledby="tab1">...描述内容...</div>
<div role="tabpanel" id="panel2" aria-labelledby="tab2" hidden>...评价内容...</div>

必须用 JavaScript 处理 aria-selected 切换、隐藏/显示对应面板以及键盘方向键切换选项卡。

手风琴/折叠面板

<button aria-expanded="false" aria-controls="sect1">了解更多</button>
<div id="sect1" role="region" hidden>...详细内容...</div>

当展开时,按钮的 aria-expanded 设为 "true",并移除内容的 hidden

错误消息关联 使用 aria-describedby 将错误消息连接到输入框。

<label for="username">用户名</label>
<input id="username" type="text" aria-describedby="username-error" aria-invalid="true">
<span id="username-error" role="alert">用户名必须是 4-20 个字符</span>

aria-invalid 告知当前值无效,role="alert" 让错误信息被动态宣告。

4.3 ARIA 使用第一规则

如果可以使用原生的 HTML 元素或属性满足所需的语义和行为,则不要使用 ARIA,而是直接使用 HTML。 例如,优先使用 <button> 而非 <div role="button">。 ARIA 仅用来补充原生语义的不足,误用 ARIA 反而会造成障碍。

五、设计、颜色与对比度

可访问性不仅涉及代码,设计决策同样影响深远。

  • 颜色对比度:对比度比率的计算方法基于 WCAG 公式。工具如 WebAIM Contrast Checker 可自动检测。
    • 正常文本:至少 4.5:1 (AA);7:1 (AAA)。
    • 大文本 (18px 粗体或 24px 以上):至少 3:1 (AA);4.5:1 (AAA)。
  • 非颜色标识:表单错误、图表数据不应仅通过颜色传递信息,应结合图标或文本。
  • 焦点指示器:保持清晰可见的 :focus 样式,切勿使用 outline: none 而不提供替代方案。可自定义如:
    :focus-visible {
      outline: 3px solid #ffbf47;
      outline-offset: 2px;
    }
    

六、测试与自动化工具

将可访问性测试融入开发流程,推荐采用“自动化 + 手动”的混合策略。

  • 浏览器内置工具:Chrome DevTools 的 Lighthouse 审计、Edge 的 Accessibility 检查器。
  • 专用浏览器扩展:axe DevTools、WAVE、Siteimprove Accessibility Checker。
  • 屏幕阅读器测试:使用 NVDA (Windows) 或 VoiceOver (macOS/iOS) 实际操作页面,仅靠键盘导航,体验无鼠标交互。
  • 自动化 CI 集成:将 axe-core 纳入单元测试或端到端测试,在合并代码时就拦截大部分问题。

七、进阶技巧与常见陷阱

  • 跳过导航链接:作为页面第一个可聚焦元素,链接到 #main-content,为键盘用户提供便利。
  • 动画与移动:允许用户暂停、停止或隐藏移动、闪烁、滚动的内容。使用 prefers-reduced-motion 媒体查询尊重系统设置:
    @media (prefers-reduced-motion: reduce) {
      * {
        animation-duration: 0.01ms !important;
        transition-duration: 0.01ms !important;
      }
    }
    
  • 常用陷阱
    1. 使用 div 模拟按钮却遗漏键盘事件和角色。
    2. 不正确地使用 aria-hidden="true" 隐藏了屏幕阅读器需要的内容。
    3. 模态框未管理焦点,关闭后焦点丢失。
    4. 缺乏 lang 属性或部分内容语言标记错误,导致屏幕阅读器发音异常。

八、从合规到卓越

达到 WCAG AA 只是起点,真正的包容性设计思考各类用户场景:色盲、低视力、阅读障碍、行动受限、认知差异等。将无障碍融入设计系统、组件库和开发规范,持续收集残障用户的反馈,才能构建优雅且普适的数字体验。

学习资源: