HTML可访问性是系统级约束而非附加功能:原生标签语义优先于ARIA角色,div模拟nav/button需手动补全焦点、角色、事件等行为,否则辅助技术无法识别;表单错误须用aria-describedby关联role="alert"文案,设计系统必须明确键位交互、焦点样式、颜色对比度等底层规则。

网页设计系统中,HTML可访问性不是附加功能,而是系统级约束条件——它决定了组件能否被键盘用户跳过、屏幕阅读器识别为导航区域,或在JS失效时仍保留语义结构。
为什么不能用 div 模拟 nav 或 button
用 div 套 onclick 写一个“导航栏”,对视觉用户没区别,但对辅助技术来说,它只是个空容器。浏览器不会给它自动添加焦点、角色或键盘事件支持。
- 必须手动加
tabindex="0"才能聚焦,但按Enter不会触发,还得监听事件 - 屏幕阅读器读不出“这是导航”,除非补
role="navigation"和aria-label -
button元素天生支持空格/Enter 触发、disabled状态、表单提交行为;div模拟的按钮无法参与表单提交,也不能被form的reset重置 - 设计系统若允许组件库返回非语义 HTML(如用
span渲染开关),下游项目一接入就埋下可访问性债
role 和原生标签冲突时以谁为准
当原生语义与 ARIA 角色矛盾,浏览器和辅助技术优先信任原生标签。比如:<button role="link">点击跳转</button> 会被读作“按钮”,不是“链接”——因为 button 的隐含 role 是 button,ARIA 不会覆盖它。
- 正确做法:想表达链接语义,就用
a标签;需要按钮行为但外观像链接,用button+ CSS 修饰,再加aria-label明确意图 - 只有原生标签无法表达语义时才用 ARIA:比如标签页(
tablist)、树形控件(tree)、模态框(dialog) - 禁止滥用
role="presentation"或aria-hidden="true"隐藏内容——这会直接让屏幕阅读器忽略整个节点,包括其子元素
表单错误提示为什么 aria-invalid 不够用
aria-invalid="true" 只告诉辅助技术“这个字段错了”,但不说明错在哪、怎么改。用户听到“无效”,却不知道是格式不对、必填未填,还是邮箱域名不存在。
立即学习“前端免费学习笔记(深入)”;
- 必须配合
aria-describedby指向具体错误文案的id,且该文案需用role="alert"或aria-live="polite"确保实时播报 - 错误文案不能仅靠颜色区分(如红字),要加图标或文字前缀(如“错误:邮箱格式不正确”)
- 提交失败后,焦点应自动移到第一个出错字段,而非停留在提交按钮上——否则键盘用户得手动 Shift+Tab 才能回去
- 如果错误信息是动态插入的 DOM 节点,确保它在 DOM 中紧邻对应输入框,否则
aria-describedby关联可能失效
设计系统交付物里最容易漏掉的可访问性项
组件文档常写“支持键盘操作”,但没说明具体键位;标称“符合 WCAG”,却没定义对比度阈值或焦点样式规范。这些模糊地带,上线后立刻暴露。
- 每个交互组件必须明确标注:哪些键触发什么动作(如 Tab 进入、←→ 切换标签、Enter 激活、Esc 关闭)
- 焦点样式不能只靠
:focus默认轮廓,要提供可配置的高对比度 outline 或 ring,并禁用outline: none - 图标按钮必须带
aria-label或包裹span文本,纯 SVG 无title或aria-label就是不可访问的 - 所有颜色组合(尤其是文本/背景)需在设计系统层面固化对比度检测流程,不能依赖开发后期人工检查
可访问性在设计系统里不是 checklist 里的最后一项,而是约束组件 API 设计、DOM 结构输出、状态管理逻辑的底层规则——漏掉任意一环,下游应用就不得不自己打补丁,而补丁越堆越多,最终变成没人敢动的黑盒。



















