| | 表单标签 |
|
+ 占位符 |
💡 提示:HTML5 语义元素在 IE9+ 中支持良好,放心使用。
2. ARIA 属性:增强而非替代
ARIA(Accessible Rich Internet Applications)是一组属性,用于补充 HTML 的语义。但请记住第一条规则:如果原生 HTML 能实现,就不要用 ARIA。
常见 ARIA 使用场景
2.1 动态内容更新
当页面局部刷新时,屏幕阅读器可能不会自动播报。使用 aria-live 区域:
<div aria-live="polite" id="status-message"></div>
<script>
function updateStatus(msg) {
document.getElementById('status-message').textContent = msg;
}
// 调用后屏幕阅读器会朗读新内容
updateStatus('数据加载完成');
</script>
aria-live="polite":等待用户空闲时播报(适合状态更新)
aria-live="assertive":立即打断播报(适合错误提示)
2.2 自定义组件
如果你必须实现自定义下拉菜单,需要添加角色和状态:
<div role="combobox" aria-expanded="false" aria-haspopup="listbox">
<input type="text" aria-autocomplete="list" aria-controls="listbox" />
<ul id="listbox" role="listbox" hidden>
<li role="option" tabindex="-1">选项一</li>
<li role="option" tabindex="-1">选项二</li>
</ul>
</div>
注意:ARIA 只改变语义,不提供键盘交互。你必须手动实现方向键导航、Enter 选择等行为。
常见 ARIA 坑点
aria-hidden="true" 会完全隐藏元素,但元素仍可聚焦——需配合 tabindex="-1"。
- 不要给
加 role="button",多此一举。
aria-label 会覆盖元素内的文本,确保描述准确。
3. 键盘导航:让所有功能可触达
键盘用户(包括使用屏幕阅读器、运动障碍者)依赖 Tab 键、方向键、Enter/Space 操作。你的网站必须支持完整的键盘操作。
3.1 焦点管理
- 可见焦点:永远不要用
outline: none 移除焦点样式,除非你提供了替代方案。
/* 错误:完全移除焦点 */
button:focus { outline: none; }
/* 正确:自定义更明显的焦点样式 */
button:focus-visible {
outline: 3px solid #1a73e8;
outline-offset: 2px;
}
- 跳过导航链接:在页面顶部添加“跳到主内容”链接,方便键盘用户跳过重复的导航。
<a href="#main" class="skip-link">跳到主内容</a>
<style>
.skip-link {
position: absolute;
left: -9999px;
top: 0;
background: #fff;
padding: 8px;
z-index: 100;
}
.skip-link:focus {
left: 0;
}
</style>
3.2 焦点陷阱(模态框)
打开模态框时,焦点应被限制在框内,关闭后返回触发元素。
function trapFocus(modal) {
const focusable = modal.querySelectorAll('button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])');
const first = focusable[0];
const last = focusable[focusable.length - 1];
modal.addEventListener('keydown', (e) => {
if (e.key === 'Tab') {
if (e.shiftKey && document.activeElement === first) {
e.preventDefault();
last.focus();
} else if (!e.shiftKey && document.activeElement === last) {
e.preventDefault();
first.focus();
}
}
});
}
💡 提示:现代浏览器支持 元素,自带焦点陷阱和 Esc 关闭,优先使用。
4. 颜色与对比度:不只是美观
低对比度文字对视力障碍者、老年人以及强光下的所有用户都是灾难。WCAG 2.1 要求:
- 普通文本对比度至少 4.5:1
- 大文本(18pt+ 或 14pt 粗体)至少 3:1
- 非文本元素(图标、边框)至少 3:1
检查工具
- Chrome DevTools:Elements 面板 → 颜色选择器显示对比度
- 在线工具:WebAIM Contrast Checker
不要只依赖颜色传达信息
<!-- 错误:仅用红色表示错误 -->
<input style="border-color: red" />
<!-- 正确:颜色 + 图标 + 文本 -->
<input aria-invalid="true" aria-describedby="error-msg" />
<span id="error-msg" style="color: red">
<span aria-hidden="true">⚠️</span> 邮箱格式不正确
</span>
5. 图片与多媒体
5.1 图片替代文本
- 有意义的图片:

- 装饰性图片:

(空 alt,屏幕阅读器跳过)
- 复杂图表:提供详细描述,可用
aria-describedby 关联。
5.2 视频字幕与音频描述
- 为视频提供
字幕
- 为纯音频内容提供文字稿
- 自动播放视频必须静音,且提供暂停按钮
6. 表单无障碍
表单是无障碍问题的重灾区。确保每个输入都有可访问的标签。
<form>
<div>
<label for="name">姓名</label>
<input type="text" id="name" name="name" required aria-required="true" />
</div>
<div>
<label for="email">邮箱</label>
<input type="email" id="email" name="email" aria-describedby="email-hint" />
<small id="email-hint">我们不会公开你的邮箱</small>
</div>
<button type="submit">提交</button>
</form>
注意:
- 不要用
placeholder 代替 ,占位符在输入后消失。
- 错误提示需用
aria-describedby 关联到输入框,并设置 aria-invalid="true"。
- 分组相关控件用
和
。
7. 测试与工具
7.1 自动化测试
- axe DevTools:浏览器扩展,快速扫描常见问题。
- Lighthouse:Chrome DevTools 内置,生成无障碍报告。
- Pa11y:命令行工具,可集成到 CI。
npm install -g pa11y
pa11y https://example.com
7.2 手动测试
- 键盘测试:拔掉鼠标,只用 Tab、Shift+Tab、Enter、Space、方向键操作整个页面。
- 屏幕阅读器:Windows 用 NVDA(免费),macOS 用 VoiceOver(内置)。
- 放大测试:浏览器放大到 200%,检查布局是否错乱。
💡 提示:自动化工具只能发现约 30% 的问题,手动测试必不可少。
8. 常见误区与最佳实践总结
| 误区 | 正确做法 | |——|———-| | 用 div 做按钮 | 使用 | | 移除焦点轮廓 | 自定义更明显的焦点样式 | | 仅用颜色表示状态 | 颜色+图标+文本 | | 所有图片都加 alt | 装饰图片用 alt="" | | 忽略键盘导航 | 确保所有功能可键盘操作 | | 滥用 ARIA | 优先原生 HTML |
结语
Web 无障碍不是一次性的任务,而是持续的过程。从今天开始,在你的项目中:
- 使用语义化 HTML
- 确保键盘可操作
- 检查颜色对比度
- 为图片添加恰当的 alt
- 用屏幕阅读器测试关键流程
记住:无障碍设计惠及所有人。当你为视障用户优化时,你也让所有用户在强光下、在嘈杂环境中、在临时受伤时受益。
延伸阅读
现在,打开你的项目,运行一次 Lighthouse 无障碍审计,看看能发现多少改进点。