网页无障碍访问(a11y):开发者实用指南
学习必要的无障碍原则、ARIA 属性、键盘导航模式以及测试工具,让你的网页应用对所有人都可用。
全球超过 13 亿人——占世界人口的 16%——患有某种形式的残障。网页无障碍访问确保你的网站能够服务于依赖屏幕阅读器、键盘导航、开关控制或其他辅助技术的用户。除了包容性之外,无障碍网站在搜索中排名更高、在移动端表现更好,而且通常也是法律的要求。
四大 POUR 原则
网页内容无障碍指南(WCAG)建立在四个核心原则之上。内容必须做到:
- 可感知(Perceivable) — 信息必须以用户能够感知的方式呈现(不仅限于视觉)。
- 可操作(Operable) — 所有功能必须可通过键盘使用。
- 可理解(Understandable) — 内容和界面必须易于理解。
- 健壮性(Robust) — 内容必须能被辅助技术解析。
WCAG 2.2 定义了三个合规级别:
- A — 最低标准(必须达到)
- AA — 大多数组织的标准目标
- AAA — 最高标准(部分内容的理想目标)
大多数法律要求(ADA、EN 301 549、EAA)都要求达到 AA 合规。
优先使用语义化 HTML
对无障碍访问影响最大的事情就是为任务选用正确的 HTML 元素。浏览器和屏幕阅读器本身就知道如何处理语义化元素:
<!-- ❌ Div 堆砌 — 没有语义 -->
<div class="header">
<div class="nav">
<div class="nav-item" onclick="navigate()">Home</div>
</div>
</div>
<!-- ✅ 语义化 HTML — 屏幕阅读器可以理解 -->
<header>
<nav>
<a href="/">Home</a>
</nav>
</header>
关键语义化元素及其作用:
| 元素 | 作用 |
|---|---|
<header>、<footer> |
地标区域 |
<nav> |
导航地标 |
<main> |
主要内容(每页一个) |
<aside> |
补充内容 |
<h1>–<h6> |
标题层级 |
<button> |
交互控件 |
<a href> |
导航链接 |
<label> |
表单字段标签 |
<table> |
表格数据 |
图片与替代文本
每张有意义的图片都需要一个描述其内容的 alt 属性。装饰性图片使用空的 alt="",让屏幕阅读器跳过它们:
<!-- 有意义的图片 -->
<img src="chart.png" alt="Bar chart showing 40% increase in revenue Q1 2026">
<!-- 装饰性图片 -->
<img src="divider.svg" alt="">
<!-- 图标按钮 — 描述操作,而非图标本身 -->
<button>
<img src="trash.svg" alt="Delete item">
</button>
<!-- 避免:冗余的"图片是"表述 -->
<!-- ❌ --> <img src="cat.jpg" alt="Image of a cat">
<!-- ✅ --> <img src="cat.jpg" alt="Orange tabby cat sitting on a windowsill">
色彩对比度
有低视力或色觉障碍的用户依赖文本与背景之间足够的对比度。
WCAG AA 要求:
- 普通文本(< 18pt):最低 4.5:1 对比度
- 大文本(≥ 18pt 或 14pt 粗体):最低 3:1 对比度
- UI 组件和图形对象:最低 3:1
不要仅靠颜色来传递信息:
<!-- ❌ 仅用颜色表示状态 -->
<span class="text-red-500">Error</span>
<!-- ✅ 颜色 + 图标 + 文字 -->
<span class="text-red-500 flex items-center gap-1">
<svg aria-hidden="true"><!-- error icon --></svg>
Error: Invalid email address
</span>
表单:标签、错误提示与说明
每个表单控件都需要一个可见的关联标签:
<!-- ✅ 显式标签关联 -->
<label for="email">Email address</label>
<input id="email" type="email" aria-describedby="email-hint email-error">
<p id="email-hint" class="text-sm text-gray-500">We'll never share your email.</p>
<p id="email-error" role="alert" class="text-sm text-red-600" hidden>
Please enter a valid email address.
</p>
表单无障碍的关键模式:
- 使用
for/id将标签与输入框关联 - 使用
aria-describedby提供提示文本和错误信息 - 使用
role="alert"或aria-live="polite"处理动态错误提示 - 使用
aria-required="true"或原生required属性 - 使用
<fieldset>和<legend>将相关输入项分组
键盘导航
所有交互元素必须可通过键盘访问和操作:
- Tab — 向前移动焦点至可聚焦元素
- Shift+Tab — 向后移动
- Enter/Space — 激活按钮、复选框
- 方向键 — 在组件内导航(菜单、标签页、滑块)
- Escape — 关闭模态框、收起下拉菜单
焦点指示器必须可见。在没有替代方案的情况下,绝对不要这样做:
/* ❌ 完全隐藏焦点指示器 */
*:focus { outline: none; }
/* ✅ 自定义焦点样式,仍然可见 */
*:focus-visible {
outline: 2px solid #3b82f6;
outline-offset: 2px;
}
ARIA:何时使用以及如何使用
ARIA(Accessible Rich Internet Applications)属性在 HTML 本身不足以表达语义时,为元素添加语义信息。ARIA 第一条规则:如果原生 HTML 可以胜任,就不要使用 ARIA。
<!-- 为没有可见标签的元素添加标签 -->
<button aria-label="Close dialog">✕</button>
<!-- 描述展开状态 -->
<button aria-expanded="false" aria-controls="menu">Menu</button>
<ul id="menu" hidden>...</ul>
<!-- 动态内容的实时区域 -->
<div aria-live="polite" aria-atomic="true">
<!-- 屏幕阅读器会朗读此区域的变化 -->
3 results found
</div>
<!-- 当语义化元素不可用时使用地标角色 -->
<div role="search">
<input type="search" placeholder="Search...">
</div>
单页应用与模态框的焦点管理
在单页应用中,页面导航不会触发浏览器的焦点重置。当"页面"加载时,应将焦点移动到有意义的位置:
// 导航后,将焦点移至主标题
document.querySelector("h1")?.focus();
对于模态框:
- 模态框打开时,将焦点移至其内部第一个可聚焦元素
- 模态框打开期间,将焦点锁定在其内部(防止 Tab 键访问背后的内容)
- 模态框关闭时,将焦点返回到触发它的元素
无障碍测试
自动化工具(可发现约 30-40% 的问题)
- axe DevTools 浏览器扩展
- Lighthouse Chrome DevTools 中的无障碍审计
- WAVE 浏览器扩展
手动测试(完整覆盖所必需)
- 纯键盘导航 — 拔掉鼠标,仅用键盘浏览整个网站
- 屏幕阅读器测试 — NVDA + Firefox(Windows)、VoiceOver + Safari(Mac/iOS)
- 放大到 200% — 确保内容不会丢失或重叠
- 色盲模拟 — 浏览器 DevTools → Rendering → Emulate vision deficiencies
可读性
简明语言有助于认知障碍用户的无障碍访问。使用我们的可读性评分工具检查内容的阅读难度——面向大众的内容建议控制在 8-10 年级阅读水平。
今天就能实现的快速改进
- 为所有图片添加
alt文本 - 确保所有表单输入项都有关联的
<label>元素 - 检查正文文本的色彩对比度是否达到 4.5:1
- 添加
:focus-visible样式,不要在没有替代方案的情况下移除轮廓线 - 用
<button>表示操作,用<a href>表示导航(不要反过来用) - 在
<html>元素上添加lang="en"(或适当的语言代码) - 每页使用一个
<h1>,并保持合理的标题层级结构
无障碍访问不是附加功能——它是产品质量的体现。从一开始就构建无障碍产品,远比事后改造成本更低,也能让你的产品对所有人都更友好。