必须将伪元素宽高设为0、设置content: ""和position: absolute,三边透明边框+一边实色边框即可生成小三角;需配合精确定位与opacity过渡实现平滑显隐。

用 :before 或 :after 生成小三角,别用图片或 SVG
小三角本质是用纯 CSS 边框技巧实现的:把一个无宽高的元素(比如 :after)的三边设为透明边框,剩下一侧设为实色边框,再配合 transform: rotate() 或直接利用边框交汇点,就能得到指向性三角。关键点是——必须给该伪元素设置 content: "",否则不渲染;同时要加 position: absolute 并精确定位到 tooltip 框边缘。
常见错误是三角位置偏移、尖角模糊或在高缩放下像素错位。解决办法是统一用 px 单位控制三角大小(比如 border-width: 6px),避免用 em 或百分比;三角的 top/left 值需和 tooltip 的 border-radius、padding 协调,例如 tooltip 上边距 10px,三角就设 top: -6px(6px 是 border-width 的一半?不对,是完整值,因为边框是从中心向外画的)。
淡入淡出必须用 opacity + transition,不能只靠 visibility
只设 visibility: hidden / visible 不会触发动画,它没有中间状态。正确做法是:初始 opacity: 0 + pointer-events: none,显示时改为 opacity: 1 + pointer-events: auto,并在 tooltip 容器上写 transition: opacity 0.2s ease-in-out。注意两点:
-
transition必须写在「始终存在」的元素上(即 tooltip 容器本身),不能只写在 hover 状态里 - 如果 tooltip 内容有文字或图标,建议额外加
transition: opacity 0.2s ease-in-out, transform 0.2s ease-in-out,避免文字在低 opacity 下渲染发虚 - 不要用
display: none控制显隐——它无法过渡,且会破坏动画连贯性
hover 触发区域要包含触发元素和 tooltip 本身,否则鼠标移过去就消失
这是最常被忽略的交互缺陷。如果只对按钮写 .btn:hover .tooltip,那么当鼠标从按钮移到 tooltip 上时,:hover 状态丢失,tooltip 立刻开始淡出。解决方法是把 tooltip DOM 放进触发元素内部(如 <span class="trigger">hover me<span class="tooltip">tip</span></span>),然后用 .trigger:hover .tooltip;或者用相邻兄弟选择器 + ~ 配合足够大的 margin-top 留出悬停缓冲区。
立即学习“前端免费学习笔记(深入)”;
更稳妥的做法是加一点延迟:用 transition-delay 控制淡出时机,比如 .tooltip { transition: opacity 0.2s ease-in-out 0.1s; },让淡出晚 100ms 开始,给用户留出移动鼠标的窗口。
移动端兼容要注意 :hover 失效,得靠 JS 补充 focus 和 touchstart
CSS-only tooltip 在 iOS Safari 和部分安卓浏览器里,:hover 只在点击后短暂触发一次,松手就失效。单纯加 @media (hover: hover) 无法解决真实交互问题。实际项目中必须补充 JS:
- 监听
touchstart给触发元素加临时 class(如is-active),用该 class 控制 tooltip 显示 - 同时监听
focus和blur,支持键盘导航用户 - 避免用
click,否则在桌面端会和:hover冲突,造成双触发
小三角本身不受影响,但整个显隐逻辑得退化为「JS 控制 class,CSS 只负责样式和过渡」——这才是真正跨端可用的方案。
三角的定位数值、过渡 timing function、hover 区域连通性,这三点任意一个没对齐,tooltip 就会闪、跳、错位或响应迟钝。动手前先在 DevTools 里关掉动画(prefers-reduced-motion: reduce 测试也要过),再开回来调参数。


















