可访问性要求
组件开发在现代前端工程中扮演着核心角色,而可访问性(a11y)是确保所有用户平等使用产品的关键。从键盘导航到屏幕阅读器兼容,需在组件设计阶段系统化落实规范。
可访问性基础原则
遵循WCAG 2.1 AA级标准是行业基准,包含四大核心原则:
- 可感知性:信息必须通过多种感官通道传递
- 可操作性:交互方式不能依赖单一操作方式
- 可理解性:界面行为和内容必须清晰明确
- 健壮性:兼容当前和未来的辅助技术
// 错误示例:纯图标按钮缺少文本说明
<button onClick={handleSearch}>
<Icon name="search" />
</button>
// 正确实现:提供隐藏文本
<button onClick={handleSearch} aria-label="搜索">
<Icon name="search" />
<span className="visually-hidden">搜索</span>
</button>
键盘导航规范
所有交互组件必须支持完整的键盘操作链:
- Tab键聚焦顺序需符合DOM流顺序
- 自定义组件需实现
tabindex="0"
或-1
控制 - 复合组件(如菜单)需实现箭头键导航
// 自定义下拉菜单键盘事件处理
menu.addEventListener('keydown', (e) => {
const items = Array.from(menu.querySelectorAll('[role="menuitem"]'));
const currentIndex = items.indexOf(document.activeElement);
switch(e.key) {
case 'ArrowDown':
e.preventDefault();
items[(currentIndex + 1) % items.length].focus();
break;
case 'ArrowUp':
e.preventDefault();
items[(currentIndex - 1 + items.length) % items.length].focus();
break;
}
});
ARIA属性应用
WAI-ARIA规范是弥补HTML语义不足的重要工具:
角色定义
role="navigation"
:主要导航区域role="alert"
:紧急通知内容role="dialog"
:模态对话框容器
状态管理
aria-expanded
:折叠/展开状态aria-disabled
:禁用状态aria-live
:动态内容更新区域
<!-- 树形控件ARIA实现示例 -->
<div role="tree">
<div role="treeitem" aria-expanded="true" tabindex="0">
父节点
<div role="group">
<div role="treeitem" tabindex="-1">子节点1</div>
<div role="treeitem" tabindex="-1">子节点2</div>
</div>
</div>
</div>
色彩对比度要求
文本内容需满足最小对比度:
- 普通文本:4.5:1(AA级)
- 大号文本(18pt+/24px+):3:1
- 非文本UI组件(如图标):3:1
使用工具验证:
/* 通过CSS变量管理可访问色彩 */
:root {
--text-primary: #333;
--bg-primary: #fff;
/* 对比度7.3:1 */
}
.error-text {
color: #d32f2f;
background-color: #ffebee; /* 对比度4.6:1 */
}
焦点管理策略
可见焦点样式是键盘用户的导航生命线:
- 禁止使用
outline: none
而不提供替代方案 - 自定义焦点样式需满足3:1对比度
- 模态对话框需实现焦点陷阱
/* 自定义焦点样式 */
button:focus {
outline: 3px solid #005fcc;
outline-offset: 2px;
box-shadow: 0 0 0 4px rgba(0, 95, 204, 0.3);
}
/* 高对比度模式适配 */
@media (forced-colors: active) {
button:focus {
outline-color: Highlight;
}
}
表单组件规范
表单是Web可访问性的关键战场:
- 所有表单控件必须关联
<label>
- 错误提示需同时包含文本和ARIA通知
- 复杂表单需提供分组说明
// React表单错误处理示例
<>
<label htmlFor="email">电子邮箱</label>
<input
id="email"
type="email"
aria-invalid={!!errors.email}
aria-describedby="email-error"
/>
{errors.email && (
<div id="email-error" role="alert" className="error-message">
{errors.email.message}
</div>
)}
</>
动态内容更新
异步加载内容需考虑辅助技术感知:
aria-live="polite"
:非紧急更新aria-live="assertive"
:重要即时更新aria-busy
:加载状态指示
// 实时搜索结果更新
<div aria-live="polite">
{searchResults.length > 0 && (
<p>找到{searchResults.length}条结果</p>
)}
</div>
移动端特殊考量
触控设备需兼顾多种交互方式:
- 确保触摸目标不小于48x48px
- 避免仅依赖悬停状态显示关键信息
- 双指缩放不能被禁用
/* 触摸友好按钮 */
.touch-button {
min-width: 48px;
min-height: 48px;
padding: 12px;
}
测试验证流程
可访问性必须纳入开发流水线:
- 自动化扫描(axe-core、Lighthouse)
- 键盘导航手动测试
- 屏幕阅读器测试(NVDA+Firefox组合)
- 高对比度模式验证
// package.json测试脚本配置
{
"scripts": {
"test:a11y": "axe ./build && jest --config a11y-test.config.js"
}
}
文档与注释要求
组件文档必须包含可访问性章节:
### 可访问性说明
- 键盘操作:
- Enter键:激活按钮
- 方向键:切换选项
- ARIA属性:
- `role="combobox"`
- `aria-haspopup="listbox"`
- 屏幕阅读器提示:
- 聚焦时朗读"选择城市,下拉菜单"
性能与可访问性平衡
复杂交互需考虑低端设备:
- 避免过度ARIA导致屏幕阅读器冗余
- 动画需提供
prefers-reduced-motion
支持 - 延迟加载内容需保持DOM顺序稳定
/* 减少动画选项 */
@media (prefers-reduced-motion: reduce) {
* {
animation-duration: 0.01ms !important;
transition-duration: 0.01ms !important;
}
}
本站部分内容来自互联网,一切版权均归源网站或源作者所有。
如果侵犯了你的权益请来信告知我们删除。邮箱:cc@cccx.cn