> 文章列表 > css tooltip (web.dev)

css tooltip (web.dev)

css tooltip (web.dev)

目录

  • 版权
  • 介绍
  • tool-tip
    • 在上居中
    • 动画效果
    • 宽度
    • 边界
  • tool-tip::after
    • 范围
    • 锥形渐变
    • -webkit-mask
    • 尖角怎么来的?
  • 附录
    • 完整代码

版权

本文为原创, 遵循 CC 4.0 BY-SA 版权协议, 转载需注明出处: https://blog.csdn.net/big_cheng/article/details/130262213.

介绍

https://web.dev/building-a-tooltip-component/ 介绍了一个tooltip 的实现. 本文将它简化并分析原理. 效果对比图如下:
在这里插入图片描述
鼠标hover 到父容器时, tooltip 浮现.

tool-tip

tooltip 实现为子元素:

    a<BR>b<BR>c<BR>preceding<div id="ct" style="display: inline-block; border: 1px solid;">div content div content div content<tool-tip>this is tip content</tool-tip></div>

浏览器实际将这个不认识的"tool-tip" 元素视为"div".

在上居中

tooltip 绝对定位, 停靠在父容器上方:

tool-tip {--_triangle-size: 7px;position: absolute;bottom: calc(100% + 0.75ch + var(--_triangle-size));......

为实现水平居中, 首先将左边缘居中, 再往左偏移自身宽度的一半:

	left: 50%;transform: translateX(-50%) translateY(3px);

动画效果

通过修改"opacity" 来显示tooltip, 并且微调y 值实现微微地’跳动’:

tool-tip {......opacity: .2;transform: translateX(-50%) translateY(3px);transition: opacity .2s ease, transform .2s ease;......
}
#ct {position: relative;
}
#ct:hover > tool-tip {opacity: 1;transform: translateX(-50%) translateY(0);transition-delay: 200ms;
}

“translateY” 正值是向下.

注: 为了方便调试, 初始"opacity" 改为了".2".

宽度

tool-tip {......width: max-content;max-width: 25ch;text-align: center;

按内容来定宽. 调试可发现屏宽压缩到tool-tip ‘内部’ 时, body 出现HScroll.

边界

tool-tip 没有边框线 - 通过filter 来实现类似效果:

	will-change: filter;filter: drop-shadow(0 3px 3px hsl(0 0% 0% / 15%)) drop-shadow(0 12px 12px hsl(0 0% 0% / 15%));
}

tool-tip::after

用::after 来实现tooltip 下边缘的尖角.

范围

::after 元素使用绝对定位, 占满tool-tip 的区域:

tool-tip::after {......background: white;position: absolute;z-index: -1;top: 0; right: 0; left: 0;bottom: -7px;border-bottom: 7px solid transparent;......

底部多延伸7px - 用于尖角.

调试:
a) 禁掉tool-tip 的"opacity|filter", 增加"border: 1px solid"
b) 修改::after: “background: red;”
在这里插入图片描述
可见::after 是在tool-tip (作为父容器) 的范围内, 并下延.

锥形渐变

例如横线<hr> 下方的小黑块:

<hr>
<style>#ct2 {width: 50px; height: 50px;background: white conic-gradient(from -30deg at bottom, #0000, #000 1deg 60deg, #0000 61deg);......}
</style><div id="ct2"></div>

a) 从原点竖直朝上为0度, -30度是再朝左偏(逆时针)
b) 原点"bottom" 即"bottom center" - 在所修饰容器的底部的中点
c) “#0000”: 左偏30度的这条线为黑色, 全透明(第4个零)
d) “#000 1deg 60deg”: 紧接着前一条线往右(顺时针)偏1到60度的范围为黑色(前一条透明线起消除锯齿的作用)
e) “#0000 61deg”: 最后再右偏1度黑色透明, 仍是消除锯齿
f) 360度范围内剩余的部分未定义 - 显示conic-gradient 前面定义的背景色(white)

-webkit-mask

将锥形渐变应用到::after 元素的下侧:

tool-tip::after {......-webkit-mask: conic-gradient(from -30deg at bottom, #0000, #000 1deg 60deg, #0000 61deg) bottom / 100% 50% no-repeat;mask: conic-gradient(from -30deg at bottom, #0000, #000 1deg 60deg, #0000 61deg) bottom / 100% 50% no-repeat;

a) “bottom”: 锥形渐变的mask 图的起始位置 是mask 区域的下方的中点. mask 区域 默认 是所修饰容器的border-box.
b) “100% 50%”: mask 图的大小. 这里是mask 区域横向的全部、纵向的一半.
c) “no-repeat”: 不重复, 即mask 图不会横向纵向绘制多张.

注: Chrome 浏览器使用"-webkit-mask" 而非"mask".

调试:
a) 修改::after: “background: red;”
在这里插入图片描述
可见mask 图从::after 元素底部的中点开始绘制.

因为::after “z-index” 为-1, ::after 的内容显示在tool-tip 内容的下方(不会’切掉’ 文字).

尖角怎么来的?

调试:
a) tool-tip: 禁掉"opacity", 增加"border: 1px solid"
b) ::after 修改: “background: red; border-bottom: 7px solid blue;”

::after 禁掉和启用"-webkit-mask" 的效果对比图:
在这里插入图片描述
::after 的颜色仅在锥形渐变的黑色区域范围内被保留(tool-tip border-bottom 重叠的部分也被’擦掉’ 了).

tool-tip “filter” 在尖角及两侧底边造成阴影效果. 如果禁掉"filter", 则尖角看不到, 仅底边中间有个小缺口.

附录

完整代码

<!DOCTYPE html>
<html>
<body><style>tool-tip {--_triangle-size: 7px;pointer-events: none;user-select: none;position: absolute;left: 50%;bottom: calc(100% + 0.75ch + var(--_triangle-size));z-index: 1;opacity: .2;transform: translateX(-50%) translateY(3px);transition: opacity .2s ease, transform .2s ease;width: max-content;max-width: 25ch;text-align: center;padding: 0.75ch 1.5ch;margin: 0;border-radius: 5px;background: white;color: CanvasText;will-change: filter;filter: drop-shadow(0 3px 3px hsl(0 0% 0% / 15%)) drop-shadow(0 12px 12px hsl(0 0% 0% / 15%));}tool-tip::after {content: "";background: white;position: absolute;z-index: -1;top: 0; right: 0; left: 0;-webkit-mask: conic-gradient(from -30deg at bottom, #0000, #000 1deg 60deg, #0000 61deg) bottom / 100% 50% no-repeat;mask: conic-gradient(from -30deg at bottom, #0000, #000 1deg 60deg, #0000 61deg) bottom / 100% 50% no-repeat;bottom: -7px;border-bottom: 7px solid transparent;}#ct {position: relative;}#ct:hover > tool-tip {opacity: 1;transform: translateX(-50%) translateY(0);transition-delay: 200ms;}</style>a<BR>b<BR>c<BR>preceding<div id="ct" style="display: inline-block; border: 1px solid;">div content div content div content<tool-tip>this is tip content</tool-tip></div><hr><style>#ct2 {width: 50px; height: 50px;background: white conic-gradient(from -30deg at bottom, #0000, #000 1deg 60deg, #0000 61deg);filter: drop-shadow(0 3px 3px hsl(0 0% 0% / 15%)) drop-shadow(0 12px 12px hsl(0 0% 0% / 15%));}</style><div id="ct2"></div></body>
</html>