title属性默认有效但行为不可控,仅鼠标悬停显示原生浅黄色气泡,不支持样式、延迟、位置定制,且ios safari完全禁用悬停,移动端基本失效;键盘聚焦和屏幕阅读器支持极弱,需用aria-describedby+role="tooltip"或data-tip+css伪元素等替代方案保障可访问性。

title属性在HTML中默认就有效,但行为不可控
浏览器原生支持 title 全局属性,只要给任意元素加上 title="提示文字",鼠标悬停就会显示浅黄色气泡。但它不是标准组件:无法自定义样式、位置、延迟时间,且在触摸设备(如手机)上基本不触发——iOS Safari 甚至完全禁用 title 的悬停逻辑。
移动端失效和键盘可访问性问题必须提前考虑
如果你的页面需要支持屏幕阅读器或键盘导航(比如按 Tab 键聚焦后应有提示),原生 title 几乎无效:title 不被大多数读屏软件朗读,也无法通过 focus 触发。替代方案需同时满足:
- 对鼠标悬停、键盘聚焦(
focus)、触屏长按(touchstart+ 延迟)都响应 - 用
aria-describedby关联真实<div> 提示内容,确保可访问性 <li>避免仅靠 CSS <code>:hover实现,否则键盘用户完全看不到提示
用纯CSS实现轻量级可控提示(无JS,兼容性好)
适合静态内容、无需动态内容更新的场景。核心是利用 aria-hidden="true" 隐藏原始 title,改用 data-tip 存提示文本,再用伪元素 + :hover 和 :focus-within 控制显隐:
<button data-tip="点击上传文件" aria-label="上传文件">? 上传</button>
<style>
button[data-tip] {
position: relative;
}
button[data-tip]::after {
content: attr(data-tip);
position: absolute;
bottom: 125%;
left: 50%;
transform: translateX(-50%);
background: #333;
color: #fff;
padding: 4px 8px;
border-radius: 4px;
font-size: 12px;
white-space: nowrap;
opacity: 0;
pointer-events: none;
transition: opacity 0.2s;
}
button[data-tip]:hover::after,
button[data-tip]:focus::after {
opacity: 1;
}
</style>
注意::focus 对 <button></button> 有效,但对 <span></span> 等非焦点元素需加 tabindex="0";iOS Safari 的 :hover 在非链接/按钮元素上仍可能不触发,建议关键操作始终用语义化可交互元素。
真正可靠的方案得靠少量JS补全行为边界
当需要支持触屏长按、自定义延迟、关闭按钮、或提示内容含 HTML 时,必须 JS 控制。最小可行代码只需监听三种事件并统一管理浮层 DOM:
- 监听
mouseenter+focus→ 启动 300ms 延迟显示(防误触) - 监听
mouseleave+blur+touchend→ 立即隐藏 - 监听
touchstart→ 记录起始时间,配合touchend判断是否为长按(≥500ms) - 浮层元素必须设
role="tooltip"和id,并通过aria-describedby关联回触发元素
别试图封装成“万能 tooltip 库”——多数项目只需要处理 2–3 类提示场景,硬套复杂库反而增加 bundle 体积和 focus 管理负担。
最常被忽略的是焦点环(focus ring)与提示层的视觉冲突:当元素获得焦点时,系统默认焦点框可能被提示遮盖,需用 outline-offset 或临时移除 outline 并用 box-shadow 模拟,否则 WCAG 2.4.7 会不达标。











