无障碍概述与原则
Web 无障碍(Web Accessibility,简称 a11y)是指让所有人——包括残障人士、老年人和使用不同设备的用户——都能平等地访问和使用网站内容。HTML 作为 Web 的基石,天然具备丰富的无障碍特性,理解并善用这些特性是每个前端开发者的基本素养。本节将介绍无障碍的核心理念、WCAG 四大原则,以及为什么无障碍对每个网站都至关重要。
前置知识
阅读本节前,建议先了解:Audio API 可视化
什么是 Web 无障碍
Web 无障碍指网站、工具和技术的设计和开发,使得残障人士能够有效地与之交互。这里的"残障"涵盖范围很广:
- 视觉障碍:全盲、低视力、色盲
- 听觉障碍:耳聋、听力减退
- 运动障碍:无法使用鼠标、精细动作困难
- 认知障碍:学习障碍、记忆力问题、注意力缺陷
- 临时性障碍:手臂骨折、暂时性视力下降
无障碍 ≠ 仅针对残障人士
良好的无障碍设计同样惠及:使用移动设备的用户、网络慢的用户、老年用户、在强光下使用手机的用户等。据统计,全球约有 15% 的人口拥有某种形式的残障。
WCAG 四大原则
WCAG(Web Content Accessibility Guidelines)是由 W3C 制定的国际标准,目前最新版本为 WCAG 2.2。WCAG 围绕 四大原则(POUR)组织,每个原则下有具体的指导准则。
1. 可感知(Perceivable)
信息和用户界面组件必须以可被用户感知的方式呈现。
| 准则编号 | 准则名称 | 核心要求 |
|---|---|---|
| 1.1 | 文本替代 | 所有非文本内容必须有等效的文本替代(如 alt 属性) |
| 1.2 | 时基媒体 | 为音频和视频提供字幕、描述文本和替代内容 |
| 1.3 | 适应性 | 内容在不同呈现方式下保持可用(如内容结构、顺序) |
| 1.4 | 可辨别 | 内容与背景有足够对比度、文本可缩放、不依赖颜色传达信息 |
<!-- 可感知:图片提供文本替代 -->
<img src="chart.png" alt="2024年销售额柱状图,Q1: 120万,Q2: 150万,Q3: 180万,Q4: 200万" />
<!-- 可感知:不依赖颜色传达信息 -->
<!-- 错误:仅用红色标记错误 -->
<p style="color: red;">此字段必填</p>
<!-- 正确:同时使用图标和文字 -->
<p><span aria-hidden="true">⚠️</span> 错误:此字段为必填项</p>2. 可操作(Operable)
用户界面组件和导航必须可被操作。
| 准则编号 | 准则名称 | 核心要求 |
|---|---|---|
| 2.1 | 键盘可访问 | 所有功能可通过键盘操作 |
| 2.2 | 充足时间 | 为用户提供足够时间阅读和使用内容 |
| 2.3 | 癫痫发作预防 | 不包含每秒闪烁超过 3 次的内容 |
| 2.4 | 可导航 | 提供导航、定位和查找内容的手段 |
| 2.5 | 输入模态 | 使 Web 内容更易于通过多种输入方式操作 |
<!-- 可操作:自定义按钮支持键盘交互 -->
<div role="button" tabindex="0" onclick="handleClick()" onkeydown="if(event.key==='Enter')handleClick()">
提交订单
</div>
<!-- 更好的做法:使用原生 button 元素 -->
<button type="button" onclick="handleClick()">提交订单</button>3. 可理解(Understandable)
信息和用户界面操作必须可被理解。
| 准则编号 | 准则名称 | 核心要求 |
|---|---|---|
| 3.1 | 可读 | 文本内容可读且可理解 |
| 3.2 | 可预测 | 页面行为具有一致性,不会令用户困惑 |
| 3.3 | 输入辅助 | 帮助用户避免和纠正错误 |
<!-- 可理解:明确的表单标签和错误提示 -->
<form>
<label for="email">电子邮箱</label>
<input type="email" id="email" name="email" required
aria-describedby="email-error" />
<span id="email-error" role="alert">请输入有效的邮箱地址</span>
</form>
<!-- 可理解:一致的导航模式 -->
<nav aria-label="主导航">
<ul>
<li><a href="/">首页</a></li>
<li><a href="/products">产品</a></li>
<li><a href="/about">关于</a></li>
</ul>
</nav>4. 健壮性(Robust)
内容必须能被各种用户代理(包括辅助技术)可靠地解析。
| 准则编号 | 准则名称 | 核心要求 |
|---|---|---|
| 4.1 | 兼容 | 内容与当前和未来的用户代理兼容 |
<!-- 健壮性:使用标准 HTML,声明语言和字符编码 -->
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>示例网站</title>
</head>
<body>
<!-- 使用语义化 HTML 元素 -->
<header>...</header>
<main>...</main>
<footer>...</footer>
</body>
</html>WCAG 合规级别
WCAG 定义了三个合规级别:
| 级别 | 说明 | 适用场景 |
|---|---|---|
| A | 最低级别,满足基本无障碍要求 | 所有网站都应达到 |
| AA | 中间级别,解决大多数无障碍问题 | 法律和行业标准通常要求此级别 |
| AAA | 最高级别,提供最佳无障碍体验 | 特定内容或场景建议达到 |
合规级别说明
AA 级别是大多数法律法规和行业标准的最低要求,包括欧盟的 EN 301 549、美国的 Section 508 等。大多数公共网站和商业网站应至少达到 AA 级别。
为什么无障碍重要
法律与合规
全球越来越多的国家和地区通过立法要求数字产品具备无障碍功能:
| 地区/法规 | 简述 |
|---|---|
| 美国 ADA | 禁止歧视残障人士,适用于网站和应用程序 |
| 美国 Section 508 | 联邦机构电子和信息技术必须可访问 |
| 欧盟 EN 301 549 | 欧盟无障碍指令,适用于公共部门网站和移动应用 |
| 欧洲无障碍法案(EAA) | 2025年起适用于更多产品和服务的无障碍要求 |
| 中国《信息技术 无障碍设计规范》 | GB/T 37668 标准 |
商业价值
良好的无障碍设计带来多方面的商业利益:
- 扩大用户群体:全球超过 10 亿人拥有某种形式的残障
- 提升 SEO 排名:语义化 HTML、清晰的 heading 层级、图片 alt 文本等无障碍实践直接提升 SEO
- 改善所有用户体验:无障碍设计通常使网站对所有用户都更易用
- 降低法律风险:避免因无障碍不达标而面临的法律诉讼
技术收益
无障碍驱动的最佳实践同样提升整体代码质量:
- 语义化 HTML 使代码更易理解和维护
- 良好的键盘导航提升所有用户的交互效率
- 清晰的内容结构改善 SEO 和代码可读性
- 适当的标注和标签使组件更易于复用和测试
无障碍评估方法
自动化检测
自动化工具可以快速发现约 30% 的无障碍问题:
// 使用 axe-core 进行自动化检测
// npm install axe-core<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>无障碍检测示例</title>
</head>
<body>
<script src="https://cdn.jsdelivr.net/npm/axe-core@latest"></script>
<script>
// 对整个页面运行无障碍检测
axe.run(document, {
runOnly: ['wcag2a', 'wcag2aa', 'wcag21aa', 'wcag22aa'],
// 排除特定规则
rules: {
'color-contrast': { enabled: true }
}
}).then(results => {
if (results.violations.length > 0) {
console.log('发现 ' + results.violations.length + ' 个违规:');
results.violations.forEach(violation => {
console.log(`[${violation.impact}] ${violation.description}`);
violation.nodes.forEach(node => {
console.log(' 目标:', node.target.join(', '));
});
});
} else {
console.log('未发现无障碍违规!');
}
});
</script>
</body>
</html>手动检测清单
以下是需要人工检查的关键项目:
HTML 原生无障碍特性
HTML 提供了许多内置的无障碍支持:
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>HTML 原生无障碍特性</title>
</head>
<body>
<!-- 1. 语义化标签提供结构信息 -->
<header>
<nav aria-label="主导航">
<a href="#main-content">跳到主要内容</a>
</nav>
</header>
<main id="main-content">
<!-- 2. heading 层级提供文档大纲 -->
<h1>产品列表</h1>
<section>
<h2>电子设备</h2>
<!-- 3. button 元素自动支持键盘交互 -->
<button type="button">添加到购物车</button>
<!-- 4. label 关联表单控件 -->
<label for="quantity">数量</label>
<input type="number" id="quantity" min="1" max="99" />
<!-- 5. table 的 caption 和 scope -->
<table>
<caption>产品规格表</caption>
<thead>
<tr>
<th scope="col">属性</th>
<th scope="col">规格</th>
</tr>
</thead>
<tbody>
<tr>
<th scope="row">重量</th>
<td>200g</td>
</tr>
</tbody>
</table>
</section>
<!-- 6. details/summary 实现可展开内容 -->
<details>
<summary>查看更多信息</summary>
<p>这是额外的产品描述信息...</p>
</details>
</main>
<footer>
<p>版权所有 2024</p>
</footer>
</body>
</html>无障碍开发的核心理念
原生优先
始终优先使用原生 HTML 元素,而不是用 <div> 和 JavaScript 重新实现:
<!-- 不推荐:自定义按钮 -->
<div class="btn" onclick="submit()">提交</div>
<!-- 推荐:原生按钮 -->
<button type="submit">提交</button>
<!-- 不推荐:自定义下拉菜单 -->
<div class="custom-select">
<div class="selected" onclick="toggleMenu()">请选择</div>
<div class="options">
<div onclick="select('A')">选项 A</div>
<div onclick="select('B')">选项 B</div>
</div>
</div>
<!-- 推荐:原生 select -->
<select name="choice">
<option value="">请选择</option>
<option value="A">选项 A</option>
<option value="B">选项 B</option>
</select>渐进增强
从基本的可用性出发,逐步添加增强功能:
<!-- 基础:即使 JavaScript 禁用也能工作 -->
<form action="/search" method="get">
<label for="q">搜索</label>
<input type="search" id="q" name="q" />
<button type="submit">搜索</button>
</form>
<!-- 增强:添加自动完成建议 -->
<script>
// 增强:在基础功能上添加搜索建议
const input = document.getElementById('q');
input.addEventListener('input', debounce(showSuggestions, 300));
</script>实战示例:一个无障碍友好的卡片组件
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>无障碍友好卡片示例</title>
<style>
/* 卡片基础样式 */
.card {
border: 1px solid #e0e0e0;
border-radius: 8px;
padding: 1rem;
max-width: 300px;
}
/* 焦点样式:清晰的视觉指示 */
.card:focus-within {
outline: 3px solid #0066cc;
outline-offset: 2px;
}
.card img {
width: 100%;
height: auto;
display: block;
}
.card h2 {
font-size: 1.25rem;
margin: 0.5rem 0;
}
.card p {
color: #666;
font-size: 0.9rem;
}
.card-link {
display: inline-block;
margin-top: 0.5rem;
color: #0066cc;
text-decoration: underline;
}
</style>
</head>
<body>
<!-- 使用 article 表示独立内容块 -->
<article class="card">
<!-- 有意义的 alt 文本 -->
<img src="product.jpg" alt="无线蓝牙耳机,黑色,入耳式设计" />
<!-- heading 提供标题 -->
<h2>无线蓝牙耳机</h2>
<!-- 正文描述 -->
<p>高品质无线蓝牙耳机,支持主动降噪,续航 30 小时。</p>
<!-- 价格信息 -->
<p><strong>¥299.00</strong></p>
<!-- 链接有描述性文本 -->
<a href="/products/headphones" class="card-link" aria-label="查看无线蓝牙耳机详情">
查看详情
</a>
</article>
</body>
</html>注意事项
- 无障碍不是"锦上添花":它应从一开始就融入设计和开发流程,而非事后补救
- 自动化工具不充分:工具只能检测约 30% 的问题,必须结合手动测试
- 不要仅依赖 ARIA:原生 HTML 语义通常优于 ARIA 覆盖
- 考虑临时性障碍:比如用户在明亮阳光下使用手机、手臂受伤等场景
- 测试真实用户:尽可能让使用辅助技术的真实用户参与测试
最佳实践
- 在项目开始时就建立无障碍标准,并在整个开发周期中持续执行
- 使用语义化 HTML 元素(
<header>、<main>、<nav>、<button>等) - 为所有非文本内容提供文本替代(
alt、aria-label) - 确保键盘可以操作所有交互功能
- 维护正确的 heading 层级(h1 → h2 → h3,不跳级)
- 在设计和开发阶段都进行无障碍测试
- 将无障碍检查集成到 CI/CD 流程中
下一节
继续学习:ARIA 角色(role)