title属性不可替代无障碍提示,仅限非关键辅助文案;role="tooltip"须配aria-describedby并挂载body下,隐藏用hidden而非display:none,需同步处理focus/blur及移动端长按逻辑。

title属性不能当无障碍提示用
它确实会被屏幕阅读器读出来,但只在鼠标悬停或键盘聚焦时被动触发,且不保证播报时机——焦点跳转过程中可能被跳过,也不支持自定义播报逻辑。更关键的是,移动端完全不响应 title,iOS Safari 基本忽略,安卓 Chrome 行为也不一致。
常见错误是把 title 当成正式提示组件:比如在删除按钮上写 title="确认后不可恢复",结果键盘用户 tab 到按钮时没听到警告,触屏用户长按只弹系统菜单。
- 仅限非关键、辅助性文案(如“编辑”、“更多选项”)
- 不能替代表单校验提示、操作后果说明等必须可见/可听的关键信息
- 务必同步提供显式文本(例如按钮旁加
<span class="sr-only">删除后不可恢复</span>)
role="tooltip" 必须配 aria-describedby 才生效
单独写 role="tooltip" 是无效的。屏幕阅读器不会读出内容,除非你用 aria-describedby 明确指向一个真实存在的、隐藏但可访问的 DOM 节点。
正确结构是两部分并存:
立即学习“前端免费学习笔记(深入)”;
<button aria-describedby="tip-1">删除</button> <div id="tip-1" role="tooltip" hidden>删除后不可恢复</div>
-
role="tooltip"元素必须挂载在document.body下,避免被overflow: hidden父容器裁切 - 不能嵌套在触发元素内部(如
<button><div role="tooltip">...</div></button>),否则部分读屏软件会跳过 - 隐藏时用
hidden或visibility: hidden,别用display: none——它会让屏幕阅读器彻底忽略该节点
键盘用户需要手动接管 focus 流
原生 title 不响应键盘聚焦,role="tooltip" 本身也不带交互逻辑。如果你监听了 mouseenter 显示 tooltip,却没监听 focus,键盘用户就永远看不到提示。
- 触发元素获得焦点时(
focus事件),应同步设aria-hidden="false"并显示 tooltip - tooltip 自身不要加
tabindex,避免打断操作流;若含可操作项(如“查看详情”链接),改用role="dialog"并管理焦点环 - tooltip 失去焦点时(
blur),需精准定位到“视觉和语义上紧邻触发器之后”的下一个可聚焦元素,再手动focus(),否则键盘导航会跳空
移动端长按提示必须换触发逻辑
移动端没有 hover,title 和 mouseenter 都失效。想模拟“长按唤起提示”,得用 touchstart + setTimeout,阈值建议 ≥ 600ms,防误触。
- 别只监听
touchend——手指抬起才触发,用户早已移开 - 要同时保留
mouseenter/focus和touchstart两套路径,确保鼠标、键盘、触屏全通 - tooltip 内容不能依赖视觉位置判断是否显示;要靠状态标记(如
data-tooltip-visible="true")+ aria 属性同步控制可访问性
真正麻烦的不是实现显示,而是让所有交互路径下提示都准时、准确、不丢失——尤其当 tooltip 动态挂载又卸载时,DOM 顺序、焦点归位、内存清理,每一步漏掉都会导致可访问性断裂。



















