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 的实现. 本文将它简化并分析原理. 效果对比图如下:
css tooltip (web.dev)_第1张图片
鼠标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 contenttool-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>
<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 contenttool-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>

你可能感兴趣的:(css)