Web 可访问性(Web Accessibility,简称 a11y)是指让网站能够被尽可能多的人使用,包括使用辅助技术的用户,如屏幕阅读器、键盘导航、高对比度模式等。本文将介绍可访问性的核心概念和最佳实践,帮助你构建更包容的网页。
为什么可访问性很重要
1. 包容性设计
可访问性不仅仅是为残障人士设计,它让所有用户受益:
- 视觉障碍:色盲、低视力、完全失明
- 听觉障碍:听力损失或完全失聪
- 运动障碍:无法使用鼠标,只能使用键盘
- 认知障碍:学习困难、注意力问题
- 情境限制:强光下的低对比度、嘈杂环境中的音频内容
2. 法律和合规要求
许多国家和地区都有关于数字可访问性的法律要求:
- 美国:ADA(Americans with Disabilities Act)
- 欧盟:European Accessibility Act
- 中国:《无障碍环境建设法》
3. SEO 和用户体验
可访问性实践通常也能改善 SEO:
- 语义化 HTML 结构对搜索引擎更友好
- 图片的 alt 文本帮助搜索引擎理解内容
- 良好的对比度提高所有用户的可读性
可访问性的四个原则(POUR)
1. 可感知(Perceivable)
信息和用户界面组件必须以用户可以感知的方式呈现:
<!-- 不好的例子:没有 alt 的图片 -->
<img src="chart.png" />
<!-- 好的例子:提供替代文本 -->
<img src="chart.png" alt="2024年销售增长图,显示Q1到Q4增长25%" />
2. 可操作(Operable)
用户界面组件和导航必须是可操作的:
<!-- 不好的例子:div 模拟按钮,无法键盘访问 -->
<div class="button" onclick="submit()">提交</div>
<!-- 好的例子:使用正确的按钮元素 -->
<button type="submit" onclick="submit()">提交</button>
3. 可理解(Understandable)
信息和用户界面的操作必须是可理解的:
<!-- 不好的例子:模糊的标签 -->
<input type="text" placeholder="输入" />
<!-- 好的例子:清晰的标签和说明 -->
<label for="email">电子邮箱</label>
<input
type="email"
id="email"
name="email"
placeholder="example@email.com"
aria-describedby="email-help"
/>
<p id="email-help">我们将使用此邮箱发送验证链接</p>
4. 健壮性(Robust)
内容必须足够健壮,能够被各种用户代理(包括辅助技术)可靠地解析:
<!-- 使用语义化 HTML 结构 -->
<header>
<nav aria-label="主导航">
<ul>
<li><a href="/">首页</a></li>
<li><a href="/about">关于</a></li>
</ul>
</nav>
</header>
<main>
<article>
<h1>文章标题</h1>
<p>文章内容...</p>
</article>
</main>
<footer>
<p>© 2025 版权所有</p>
</footer>
核心可访问性实践
1. 语义化 HTML
使用正确的 HTML 元素传达含义:
<!-- 不好的例子 -->
<div class="nav">
<div class="nav-item" onclick="goHome()">首页</div>
</div>
<!-- 好的例子 -->
<nav>
<a href="/">首页</a>
</nav>
2. 图片的替代文本
为所有图片提供有意义的 alt 属性:
<!-- 装饰性图片 -->
<img src="divider.png" alt="" />
<!-- 信息性图片 -->
<img src="logo.png" alt="公司Logo" />
<!-- 复杂图表 -->
<img src="sales-chart.png" alt="2024年销售增长图" />
<figure>
<figcaption>详细数据:Q1: 100万, Q2: 120万, Q3: 150万, Q4: 180万</figcaption>
</figure>
3. 表单的可访问性
确保表单对所有用户都可用:
<form>
<fieldset>
<legend>个人信息</legend>
<div class="form-group">
<label for="username">用户名 *</label>
<input
type="text"
id="username"
name="username"
required
aria-required="true"
aria-describedby="username-error"
/>
<span id="username-error" class="error" role="alert"></span>
</div>
<div class="form-group">
<label for="country">国家</label>
<select id="country" name="country">
<option value="">请选择</option>
<option value="cn">中国</option>
<option value="us">美国</option>
</select>
</div>
<div class="form-group">
<fieldset>
<legend>兴趣爱好</legend>
<input type="checkbox" id="sports" name="interests" value="sports" />
<label for="sports">运动</label>
<input type="checkbox" id="music" name="interests" value="music" />
<label for="music">音乐</label>
</fieldset>
</div>
</fieldset>
<button type="submit">提交</button>
</form>
4. 键盘导航
确保所有功能都可以通过键盘访问:
/* 可见的焦点指示器 */
:focus {
outline: 2px solid #0066cc;
outline-offset: 2px;
}
/* 键盘焦点的特殊样式 */
:focus-visible {
outline: 2px solid #0066cc;
outline-offset: 2px;
}
/* 不要完全移除焦点样式 */
button:focus:not(:focus-visible) {
outline: none;
}
// 跳过链接实现
document.querySelector(".skip-link").addEventListener("click", (e) => {
e.preventDefault();
const mainContent = document.querySelector("#main-content");
mainContent.focus();
mainContent.scrollIntoView();
});
5. ARIA 属性
当 HTML 语义不足时使用 ARIA:
<!-- 自定义下拉菜单 -->
<div
class="dropdown"
role="combobox"
aria-expanded="false"
aria-haspopup="listbox"
>
<button aria-controls="dropdown-list" aria-labelledby="dropdown-label">
选择选项
</button>
<ul id="dropdown-list" role="listbox" aria-hidden="true">
<li role="option" aria-selected="false">选项 1</li>
<li role="option" aria-selected="false">选项 2</li>
</ul>
</div>
<!-- 进度条 -->
<div
role="progressbar"
aria-valuenow="75"
aria-valuemin="0"
aria-valuemax="100"
aria-label="加载进度"
>
75%
</div>
<!-- 实时区域 -->
<div role="status" aria-live="polite" aria-atomic="true">
<p>3 条新消息</p>
</div>
6. 颜色对比度
确保文本与背景有足够的对比度:
/* 良好的对比度 - 4.5:1 以上 */
.text-primary {
color: #333333; /* 深灰 */
background-color: #ffffff; /* 白 */
}
/* 大文本可以使用稍低的对比度 - 3:1 */
.text-large {
color: #666666;
background-color: #ffffff;
font-size: 18px;
font-weight: bold;
}
/* 避免仅靠颜色传达信息 */
.error {
color: #d32f2f;
border-left: 4px solid #d32f2f; /* 额外的视觉提示 */
padding-left: 12px;
}
.error::before {
content: "⚠️ "; /* 图标提示 */
}
7. 动态内容的可访问性
处理动态更新和模态框:
// 模态框的焦点管理
function openModal() {
const modal = document.getElementById("modal");
const firstFocusable = modal.querySelector(
"button, [href], input, select, textarea",
);
const previousFocus = document.activeElement;
modal.style.display = "block";
modal.setAttribute("aria-hidden", "false");
firstFocusable.focus();
// 聚焦陷阱
modal.addEventListener("keydown", (e) => {
if (e.key === "Escape") {
closeModal();
previousFocus.focus();
}
});
}
// 页面标题更新
document.title = "新页面标题 - 我的网站";
// 通知屏幕阅读器用户
function announce(message) {
const announcement = document.createElement("div");
announcement.setAttribute("role", "status");
announcement.setAttribute("aria-live", "polite");
announcement.className = "sr-only";
announcement.textContent = message;
document.body.appendChild(announcement);
setTimeout(() => announcement.remove(), 1000);
}
可访问性测试工具
1. 自动化测试工具
# Lighthouse (Chrome DevTools 内置)
# axe-core
npm install @axe-core/cli
# Pa11y
npm install -g pa11y
pa11y https://example.com
2. 浏览器扩展
- axe DevTools:Chrome/Firefox 扩展
- WAVE:Web Accessibility Evaluation Tool
- Lighthouse:Chrome DevTools 内置
3. 手动测试清单
- 使用 Tab 键导航整个页面
- 检查所有交互元素都有焦点样式
- 使用屏幕阅读器(NVDA、JAWS、VoiceOver)测试
- 验证颜色对比度符合 WCAG 标准
- 测试放大到 200% 时的布局
- 禁用 CSS 检查页面结构
4. CSS 辅助工具
/* 屏幕阅读器专用类 */
.sr-only {
position: absolute;
width: 1px;
height: 1px;
padding: 0;
margin: -1px;
overflow: hidden;
clip: rect(0, 0, 0, 0);
white-space: nowrap;
border: 0;
}
/* 减少动画偏好 */
@media (prefers-reduced-motion: reduce) {
*,
*::before,
*::after {
animation-duration: 0.01ms !important;
animation-iteration-count: 1 !important;
transition-duration: 0.01ms !important;
}
}
/* 高对比度模式 */
@media (prefers-contrast: high) {
.button {
border: 2px solid currentColor;
}
}
总结
Web 可访问性不仅是道德责任,也是法律要求和商业需求。通过遵循 POUR 原则和最佳实践,你可以创建对所有用户都友好的网站。
记住可访问性的核心原则:
- 使用语义化 HTML - 这是最好的基础
- 提供替代内容 - 为图片、视频、音频提供替代方案
- 确保键盘可访问 - 所有功能都可以通过键盘操作
- 设计良好的对比度 - 确保内容易于阅读
- 测试验证 - 使用自动化工具和手动测试
- 持续改进 - 可访问性是持续的过程,不是一次性的任务
通过将这些实践融入日常开发流程,你将构建更加包容和健壮的 Web 应用。