原生语义标签比ARIA更可靠;缺乏键盘支持和表单行为,应优先用;有可见文本用aria-labelledby,纯图标用aria-label;aria-live="polite"用于状态提示,assertive用于关键错误;Font Awesome装饰性图标自动aria-hidden="true",功能性图标需显式声明语义。

原生语义标签比 ARIA 更可靠,能直接被屏幕阅读器识别;ARIA 是补救手段,不是替代方案。
为什么不能用 <div role="button"> 替代 <code><button></button>
浏览器对 <button></button> 有内置键盘支持(Enter/Space 触发)、焦点管理、表单提交行为和隐式 role="button";而 <div role="button"> 只告诉读屏器“这是按钮”,但没实现键盘响应、焦点进入逻辑或表单关联——用户按 Tab 能聚焦,却无法用空格触发,或提交时被忽略。
<p>常见错误现象:</p>
<ul>
<li>自定义按钮在 VoiceOver 下朗读为“按钮”,但按 Space 无反应</li>
<li>表单中用 <code><div role="button">提交</div>,form.submit() 不触发,且 Lighthouse 报“交互元素缺少键盘支持”
正确做法是:优先用 <button></button>;若必须用非按钮元素(如图标区域),需手动加 tabindex="0"、监听 keydown(捕获 Enter/Space)、并同步维护 aria-pressed 或 aria-expanded 状态。
aria-label 和 aria-labelledby 到底该写哪个?
两者都提供可访问名称,但更新机制和维护成本完全不同:aria-labelledby 指向页面中已存在的可见文本节点(如 <label id="search-label">搜索商品</label>),内容随 UI 变更自动同步;aria-label 是硬编码字符串,一旦文案改了或切换语言,就立刻失效。
典型踩坑点:
- 给搜索框写
aria-label="Search",UI 后来改成中文“查找”,读屏器仍念英文 - 同时写
aria-label和aria-labelledby,后者被完全忽略,且 axe 工具报错 - 用
aria-label描述图标按钮,但图标旁已有文字“设置”,造成重复朗读
建议规则:
- 有对应可见文本 → 用
aria-labelledby="id" - 纯图标、加载 Spinner、隐藏操作区 → 用
aria-label - 绝对不要共存
动态列表更新时,aria-live 怎么设才不打断用户?
aria-live 控制读屏器是否播报 DOM 变更,但 politeness 值选错会导致语音流崩溃:assertive 强制中断当前朗读,polite 等空闲时播报,off 完全静默。
list.js 类场景常见错误:
- 整个搜索结果容器设
aria-live="assertive",用户每输一个字,读屏器就插话“正在搜索…”,根本没法听清提示 - 错误消息区域用了
polite,结果“邮箱格式错误”被延迟 5 秒才读出,用户早点了提交 - 把
aria-live加在<ul></ul>上,但 list.js 内部用innerHTML替换整个列表,导致读屏器丢失上下文、只读新内容不报数量变化
实操建议:
- 搜索状态提示(如“找到 3 条结果”)用
aria-live="polite",包裹最小节点(如仅<div id="status"></div>) - 关键错误(如“登录失败:账号不存在”)用
aria-live="assertive",且配合role="alert" - 避免对整块区域设
aria-live,尤其不要套在 list.js 的根容器上
Font Awesome 图标要不要加 ARIA?怎么加?
Font Awesome 7 会自动检测:如果图标没任何标签属性(aria-label、aria-labelledby、title、role),就默认加 aria-hidden="true" —— 这意味着:装饰性图标不用管,它已帮你处理好。
但功能性图标必须显式声明语义,否则读屏器要么跳过,要么读成“图形”:
- 导航菜单图标(☰)→ 加
aria-label="打开侧边栏" - 搜索放大镜 → 加
aria-label="搜索"或关联aria-labelledby="search-label" - 状态图标(✅)→ 若旁边无文字,必须加
aria-label="操作成功";若有“已保存”文字,则图标应保持aria-hidden="true"
容易被忽略的一点:aria-hidden="true" 具有继承性——父元素设了它,子元素即使写 aria-hidden="false" 也无效。所以别在模态框外层 上乱加这个属性,该用 inert 或焦点锁定代替。

















