Open zhangxinxu opened 4 years ago
<a>show tip</a>
<div class="tip">替换素材让视频与众不同</div>
.tip {
display:none;
position:absolute;
top: 40px;
left: 0;
--h: 5px;
padding: 10px;
padding-top: calc(10px + var(--h));
background:linear-gradient(45deg, red, pink);
clip-path: polygon(0 var(--h),calc(20% - var(--h)) var(--h),20% 0%, calc(20% + var(--h)) var(--h),100% var(--h),100% 100%,0 100%)
}
a + .tip{
display:block;
}
.tip {
--unit: 5px;
--h: calc(100% - var(--unit));
display: inline-block;
padding: 10px 10px calc(10px + var(--unit)) 10px;
background-image: linear-gradient(to right, #ff607b, #ff3a3e);
color: #fff;
clip-path: polygon(0 5px, 1px 1px, 5px 0, calc(100% - 5px) 0, calc(100% - 1px) 1px, calc(100%) 5px, 100% calc(var(--h) - 5px), calc(100% - 1px) calc(var(--h) - 1px), calc(100% - 5px) var(--h), calc(20% - 2*var(--unit)) var(--h), calc(20% - var(--unit)) 100%, 20% var(--h), 5px var(--h), 1px calc(var(--h) - 1px), 0 calc(var(--h) - 5px));
}
<div class="tip">替换素材让视频与众不同</div>
用clip-path
+polygan()
可以实现,但是如果要加上圆角好像有点难搞?
<div class="tip">这是一段提示文字,这是一段提示文字,这是一段提示文字</div>
.tip {
max-width: 240px;
padding: 10px 10px 15px 10px;
clip-path: polygon(0% 0%, 100% 0%, 100% calc(100% - 5px), 23px calc(100% - 5px), 20px 100%, 17px calc(100% - 5px), 0% calc(100% - 5px));
background: linear-gradient(120deg, lightpink 30%, pink 70%);
}
算到头秃
也可以用inset
做一个带 border-radius 的框体 + polygan()
三角形,但是那样就不得不用伪元素了
<div class="tip show">替换素材让视频与众不同</div>
:root {
--sin15: 0.2588;
--sin30: 0.5;
--sin45: 0.7071;
--sin60: 0.866;
--sin75: 0.9659;
--outer: 6px; /* 小三角形的高度 */
--inner: 10px; /* padding */
--br: 6px; /* border-radius */
--diff-0: 0px;
--diff-15: calc(var(--sin15)* var(--br));
--diff-30: calc(var(--sin30)* var(--br));
--diff-45: calc(var(--sin45)* var(--br));
--diff-60: calc(var(--sin60)* var(--br));
--diff-75: calc(var(--sin75)* var(--br));
--diff-90: var(--br);
}
.tip {
display: none;
max-width: 200px;
padding: var(--inner);
border-radius: var(--br);
padding-bottom: calc(var(--inner) + var(--br));
color: white;
background:linear-gradient(45deg, red, pink);
--x1: calc(100% - var(--br));
--y1: calc(100% - var(--br) - var(--outer));
--x2: var(--br);
--y2: var(--y1);
clip-path: polygon(
calc(var(--x2) - var(--diff-0)) calc(var(--y2) + var(--diff-90)),
calc(var(--x2) - var(--diff-15)) calc(var(--y2) + var(--diff-75)),
calc(var(--x2) - var(--diff-30)) calc(var(--y2) + var(--diff-60)),
calc(var(--x2) - var(--diff-45)) calc(var(--y2) + var(--diff-45)),
calc(var(--x2) - var(--diff-60)) calc(var(--y2) + var(--diff-30)),
calc(var(--x2) - var(--diff-75)) calc(var(--y2) + var(--diff-15)),
calc(var(--x2) - var(--diff-90)) calc(var(--y2) + var(--diff-0)),
0 0,
100% 0,
calc(var(--x1) + var(--diff-90)) calc(var(--y1) + var(--diff-0)),
calc(var(--x1) + var(--diff-75)) calc(var(--y1) + var(--diff-15)),
calc(var(--x1) + var(--diff-60)) calc(var(--y1) + var(--diff-30)),
calc(var(--x1) + var(--diff-45)) calc(var(--y1) + var(--diff-45)),
calc(var(--x1) + var(--diff-30)) calc(var(--y1) + var(--diff-60)),
calc(var(--x1) + var(--diff-15)) calc(var(--y1) + var(--diff-75)),
calc(var(--x1) + var(--diff-0)) calc(var(--y1) + var(--diff-90)),
/* 三角形三个点 */
calc(var(--x2) + 32px) calc(var(--y2) + var(--diff-90)),
calc(var(--x2) + 26px) 100%,
calc(var(--x2) + 20px) calc(var(--y2) + var(--diff-90))
);
}
.tip.show {
display: block;
}
一开始没看懂题意,不过看懂题意之后也一脸懵比
楼上大佬就硬算出来可太秀了,我觉得我算到真的头秃了也算不出来……
所以最后借助了一个几何作图工具,画出多边形并标出坐标,应该勉强算是符合题意吧。作图工具 Geogebra
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>JS Bin</title>
</head>
<body>
<a>替换</a>
<div>替换素材让视频与众不同</div>
</body>
</html>
div {
display: none;
max-width: 200px;
padding: 10px;
padding-top: 16px;
color: white;
background:linear-gradient(45deg, red, pink);
clip-path: polygon(2px 39px,7px 40px, 190px 40px,195px 39px, 197px 35px,197px 14px,195px 11px, 190px 11px, 45px 10px,40px 0px, 35px 10px, 7px 10px,2px 11px,0px 16px, 0px 35px);
}
a:hover+div {
display: block;
}
JSBIN:demo
/**/
.icon {
display: inline-block;
width: 3em;
height: 3em;
line-height: 3em;
text-align: center;
background-color: rgba(0, 0, 0, 0.5);
color: #ffffff;
text-decoration: none;
position: relative;
}
.nu-tip {
position: absolute;
bottom: 100%;
left: -1em;
font-size: 12px;
padding: 1em 0.5em 1.5em;
line-height: 1;
white-space: nowrap;
font-style: normal;
/* 底部左右两个圆角只是近似和顶部左右两个圆角一致 */
border-radius: 0.25em 0.25em 3em 3em / 0.25em 0.25em 0.8em 0.8em;
background: linear-gradient(125deg, #fe6480, #f83534);
clip-path: polygon(0 0, 100% 0, 100% 85%, 28% 85%, 24% 95%, 20% 85%, 0 85%);
}
/* 选中触发 */
.nu-tip-box .nu-tip {
visibility: hidden;
opacity: 0;
transform: 200ms;
}
.nu-tip-box:hover .nu-tip,
.nu-tip-box:focus .nu-tip,
.nu-tip-box._open .nu-tip {
visibility: visible;
opacity: 1;
}
/* 以下是伪元素, 原理一样只是感觉这样dom 层级会少一些 */
.nu-tip2:before {
content: attr(title);
position: absolute;
bottom: 100%;
left: -1em;
font-size: 12px;
padding: 1em 0.5em 1.5em;
line-height: 1;
white-space: nowrap;
font-style: normal;
/* 底部左右两个圆角只是近似和顶部一致 */
border-radius: 0.25em 0.25em 3em 3em / 0.25em 0.25em 0.8em 0.8em;
background: linear-gradient(125deg, #fe6480, #f83534);
clip-path: polygon(0 0, 100% 0, 100% 85%, 28% 85%, 24% 95%, 20% 85%, 0 85%);
}
/* 选中触发 */
.nu-tip2:before {
visibility: hidden;
opacity: 0;
transform: 200ms;
}
.nu-tip2:hover:before,
.nu-tip2:focus:before,
.nu-tip2._open:before {
visibility: visible;
opacity: 1;
}
想了好久,感觉纯CSS没有比较完美的方法,然后借助了CSS Paint
// tooltip.js
class Tooltip {
static get inputProperties() {
return [
'--radius', // 圆角的幅度
]
}
paint(ctx, size, properties) {
const { width,height } = size;
const radius = Number(properties.get('--radius'))||5;
const deg = Math.PI / 2;
const edge = 10;
const pos = 30;
ctx.beginPath();
ctx.moveTo(radius,0);
ctx.lineTo(width-2*radius,0);
ctx.arc(width-radius,radius,radius,-deg,0);
ctx.lineTo(width,height-2*radius-edge);
ctx.arc(width-radius,height-radius-edge,radius,0,deg);
ctx.lineTo(pos+edge*0.6,height-edge);
ctx.lineTo(pos,height);
ctx.lineTo(pos-edge*0.6,height-edge);
ctx.lineTo(radius,height-edge);
ctx.arc(radius,height-radius-edge,radius,deg,2*deg);
ctx.lineTo(0,radius-edge);
ctx.arc(radius,radius,radius,-2*deg,-deg);
ctx.closePath();
ctx.fillStyle = '#000';
ctx.fill();
//ctx.stroke();
}
}
registerPaint('tooltip', Tooltip);
HTML引入模块
<script>
if (window.CSS) {
CSS.paintWorklet.addModule('tooltip.js')
}
</script>
然后在CSS直接使用
.tooptip {
padding: 10px 10px 20px 10px;
display: inline-block;
max-width: 250px;
color: #fff;
background-image: linear-gradient(-45deg,red,blue);
-webkit-mask: paint(tooltip);
}
不使用伪元素,一层标签,实现下图所示的提示效果,支持渐变背景。
原图地址
本题需要在线demo,同时附上对应的CSS代码即可,可以使用下面语法进行高亮:
本期小测无直播答疑,如果有精彩的实现会拿出来点评。
感谢您的参与!