role="tooltip" 仅是语义标记,不自动触发悬停效果,需配合 aria-describedby 关联、css 控制显隐(避免 display: none)、javascript 监听 focus/blur 和 mouseenter/mouseleave 并处理 esc 键关闭,确保键盘与鼠标用户均可访问。

role="tooltip" 本身不触发悬停效果
HTML 的 role="tooltip" 只是语义标记,告诉辅助技术“这是一个提示框”,它**不会自动显示或隐藏**,也不监听鼠标事件。你必须自己用 CSS 或 JavaScript 控制显隐逻辑。
常见错误是只写:
<div role="tooltip">保存成功</div>结果页面完全看不到——因为没写样式、也没绑定触发行为。
- 必须配合
aria-describedby或aria-labelledby指向目标元素(比如按钮),否则屏幕阅读器无法关联 - 必须设置
position: absolute或fixed,否则默认文档流中会撑开布局 - 不能依赖
:hover直接作用在 tooltip 元素上(它通常初始不可见,且无 hover 目标)
用 aria-describedby 关联触发元素和 tooltip
让 tooltip 和按钮/图标建立可访问的逻辑关系,这是 WCAG 合规的关键一步。浏览器和读屏软件靠这个定位提示内容。
示例结构:
<button id="save-btn" aria-describedby="save-tip">?</button><br><div id="save-tip" role="tooltip" class="tooltip-hidden">保存成功</div>
-
aria-describedby的值必须严格匹配 tooltip 的id - tooltip 元素应放在触发元素附近(DOM 顺序不影响功能,但利于维护)
- 避免多个元素共用同一个
id,否则aria-describedby行为未定义
CSS 控制显示/隐藏时注意可访问性状态
单纯用 display: none 会让屏幕阅读器彻底忽略 tooltip;用 visibility: hidden 或 opacity: 0 则可能仍被读出但不可见——两者都不对。
- 推荐组合:
position: absolute; opacity: 0; pointer-events: none;+aria-hidden="true"(隐藏时) - 显示时移除
aria-hidden,并确保opacity: 1; pointer-events: auto; - 不要用
height: 0; overflow: hidden;配合动画,会导致读屏器抢读中断 - 过渡动画建议用
opacity和transform,避免触发布局重排
JavaScript 绑定 hover/focus 事件时要兼顾键盘用户
仅监听 mouseenter / mouseleave 会漏掉键盘操作(如 Tab 进入按钮、Shift+Tab 离开)。WCAG 要求 tooltip 在焦点进入时显示、焦点离开时延迟隐藏(防止误触)。
- 必须监听
focus和blur,不只是mouseenter - 鼠标移出后加 300ms 延迟再隐藏(避免光标经过间隙时闪退)
- 焦点离开触发元素后,tooltip 应保持显示直到用户明确移开焦点(例如按 Tab 到下一个控件)
- 按
Esc键应主动关闭 tooltip(需监听keydown并调用tooltip.setAttribute('aria-hidden', 'true'))
复杂点不在写法,而在权衡:既要响应快,又不能干扰键盘导航节奏;既要视觉可见,又不能遮挡焦点路径。这些细节不写进 JS 就等于没做可访问性。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











