title属性最简单但有局限:延迟固定、样式不可定制、移动端不支持、无障碍不友好;应优先用aria-label/aria-describedby实现无障碍,或用js自定义tooltip(如tippy.js)确保跨端兼容。

按钮 hover 时显示提示文字,title 属性最简单但有局限
直接给 <button></button> 加 title 属性确实能触发浏览器原生 tooltip,比如:
<button title="点击保存当前设置">保存</button>但它的行为不可控:延迟时间固定(通常约 1 秒)、无法定制样式、移动端基本不触发(iOS Safari 完全不显示)、不能响应键盘焦点(对可访问性不友好)。如果你只要快速验证或内部工具用,它够用;但面向用户的产品,别依赖它。
用 aria-label 或 aria-describedby 支持屏幕阅读器
真正需要无障碍支持时,title 不是替代方案——它对屏幕阅读器的支持不稳定,有些读,有些跳过。正确做法是:
- 纯图标按钮(无可见文字)必须用
aria-label,例如:<button aria-label="删除这条记录"><i class="icon-trash"></i></button>
- 带文字按钮想补充说明,用
aria-describedby指向一个隐藏的描述元素:<button aria-describedby="save-tip">保存</button><br><div id="save-tip" class="sr-only">保存当前所有未提交的修改</div>
其中.sr-only是标准的屏幕阅读器仅读取、视觉隐藏的 CSS 类(position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden;)
自定义 tooltip 需要 JS 控制显隐和位置
要样式可控、支持键盘导航、适配移动端,就得自己实现 tooltip。核心逻辑是:
- 监听
mouseenter/focus显示,mouseleave/blur隐藏(注意:移动端需额外处理click触发) - tooltip 元素不能放在 button 内部(影响 tab 顺序),建议动态插入到
body下 - 定位推荐用
getBoundingClientRect()计算按钮位置,再用position: absolute或position: fixed放 tooltip,避免被父容器overflow: hidden截断 - 加
role="tooltip"和id,让aria-describedby能关联
const btn = document.querySelector('button[data-tooltip]');<br>const tip = document.createElement('div');<br>tip.className = 'custom-tooltip';<br>tip.role = 'tooltip';<br>tip.textContent = btn.dataset.tooltip;<br>// 插入 body,计算位置,绑定事件…
第三方库如 tippy.js 可省去定位和交互细节
如果项目允许引入依赖,tippy.js 是目前最成熟的轻量 tooltip 库。它自动处理:
- 多种触发方式(hover/focus/click)、延迟、动画、箭头、z-index
- 键盘导航(Tab 进入 tooltip,Esc 关闭)
- 响应式定位(自动避开视口边缘)
- 与 React/Vue 等框架集成简单
import tippy from 'tippy.js';<br>tippy('button[title]', {<br> content: btn => btn.title,<br> allowHTML: false,<br>});注意:仍需移除原 title 属性,改用 data-title 或其他属性,避免原生 tooltip 和自定义同时出现。
真正麻烦的不是怎么显示文字,而是判断该用哪一层:纯辅助信息走 ARIA,视觉提示要跨设备兼容就得自己控逻辑或选可靠库,而 title 只适合原型阶段快速验证。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











