本篇是张鑫旭老师的 CSS基础测试2 的阅后笔记。(另外感谢 XboxYan 的解答,逻辑很是清晰)javascript
话很少说,先上题,HTML 以下:css
<a href="javascript:" class="icon-delete css-tips" data-title="删除" role="button" >
删除
</a>
复制代码
现需实现以下效果:html
要求:java
分析完题目以后,能够看到,出题者很贴心的给了 a
标签两个 class:git
意图很明显,icon-delete
用于实现把文字替换成图标的功能,而 css-tips
用于实现气泡提示效果。 那么首先把比较简单的功能完成。github
这里能够经过把字体大小设置为 0,而后经过设置背景的方式来完成图标化:学习
.icon-delete{
display: block;
width: 30px;
height: 30px;
font-size: 0px;
background: url(./del.png) no-repeat center;
background-size: cover;
}
复制代码
这样就完成了这个简单的功能,效果以下:测试
这个功能较为复杂,咱们先不考虑各类场景,只单独的把这个气泡提示作出来。字体
给元素附加挂件的效果,这里咱们能够经过 before
和 after
伪类来作。优化
因为气泡浮于元素上方,因此这里第一反应是要用到绝对定位:
.css-tips {
position: relative;
}
.css-tips[data-title]::before,
.css-tips[data-title]::after {
content: "";
width: 20px;
height: 20px;
display: block;
position: absolute;
z-index: 1;
left: 50%;
bottom: 100%;
transform: translate(-50%, -20px);
background: #373c42;
}
复制代码
到这里,咱们成功的将 before
和 after
定位到了按钮的正上方:
接下来分别对 before
和 after
进行调整,这里咱们使用 before
来作为装填文字的容器,使用 after
做为气泡下方的箭头。
首先因为咱们并不知道提示文字长度,因此没必要设置高宽。 那么 before
就没什么好注意的了。(因为提示消息长度不固定,因此可能出现提示文本过长的状况,这样应该可以将文本换行,这个情景后面再提)
.css-tips {
position: relative;
}
.css-tips[data-title]::before,
.css-tips[data-title]::after {
content: "";
display: block;
position: absolute;
z-index: 1;
left: 50%;
bottom: 100%;
transform: translate(-50%, -20px);
background: #373c42;
}
.css-tips[data-title]:before {
content: attr(data-title);
border-radius: 3px;
padding: 6px 10px;
line-height: 18px;
text-align: left;
background-color: #373c42;
color: #fff;
font-size: 12px;
font-style: normal;
white-space: nowrap;
}
复制代码
效果以下:
上图能够看到,在气泡中间有一块黑色的遮挡,这个就是 after
了,只须要将它画成倒三角,而且贴在 before
的下方便可。
画倒三角的方法有不少,这里简单介绍一个最省事的。
咱们给一个元素添加一个 60px 的 border,而后将上下左右设置成不一样的颜色:
.border{
border: 6px solid #fff;
border-top-color: black;
border-left-color: red;
border-bottom-color: blue;
border-right-color: yellow;
}
复制代码
能够看到,四个角恰好是四个三角形,那么须要什么样的三角形,将其余的 color 设置为 transparent
便可,这里也用这种方法来画 after
.css-tips[data-title]::before,
.css-tips[data-title]::after {
content: "";
display: block;
position: absolute;
z-index: 1;
left: 50%;
bottom: 100%;
transform: translate(-50%, -20px);
background: #373c42;
}
.css-tips[data-title]:after {
content: "";
width: 0;
height: 0;
margin-bottom: -12px;
overflow: hidden;
border: 6px solid transparent;
border-top-color: currentColor;
}
复制代码
效果如图:
接下来须要作的就是在 hover 的时候显示气泡,别的时候隐藏便可,没什么好说,最终代码以下:
.icon-delete {
font-size: 0;
width: 30px;
height: 30px;
background: url(./del.png) no-repeat center;
background-size: cover;
}
.css-tips {
position: relative;
}
.css-tips[data-title]:before,
.css-tips[data-title]:after {
content: "";
display: block;
position: absolute;
z-index: 1;
left: 50%;
bottom: 100%;
transform: translate(-50%, -20px);
color: #373c42;
opacity: 0;
visibility: hidden;
}
.css-tips[data-title]:before {
content: attr(data-title);
border-radius: 3px;
padding: 6px 10px;
line-height: 18px;
text-align: left;
background-color: #373c42;
color: #fff;
font-size: 12px;
font-style: normal;
white-space: nowrap;
}
.css-tips[data-title]:after {
content: "";
width: 0;
height: 0;
margin-bottom: -12px;
overflow: hidden;
border: 6px solid transparent;
border-top-color: currentColor;
}
.css-tips[data-title]:hover:before,
.css-tips[data-title]:hover:after {
visibility: visible;
opacity: 1;
}
复制代码
效果以下:
优化要从两个方面提及:
(其实说白了都是体验优化)
咱们先来讲说体验优化,能够看到上面最后的动图效果很是僵硬,而且鼠标移动过来就马上出现气泡,假设如今有一个这样的场景:
一个表格,每一行均可以删除,用户从下往上移动鼠标,想要删除第 n 行,但因为鼠标放上去,气泡立马弹出来了,因此这个时候有可能第 n+1 行的气泡弹了出来,而且挡住了第 n 行的按钮,这个时候用户只能从新以不一样角度移动过来,这样的体验是至关不友好的。
解决上述场景,咱们有一个小技巧:延时。
咱们让气泡延迟一点出现,这样当鼠标划过的时候就并不会出现气泡,而是停留的时候才会出现,这样就不会形成上述场景了:
.css-tips[data-title]:before,
.css-tips[data-title]:after {
content: "";
display: block;
position: absolute;
z-index: 1;
left: 50%;
bottom: 100%;
transform: translate(-50%, -20px);
color: #373c42;
opacity: 0;
transition: 0.15s 0.15s;
visibility: hidden;
}
复制代码
效果以下:
到这里其实气泡也显得并不那么生硬了,固然若是愿意的话能够再增长一个过渡,显得更加灵动:
.css-tips[data-title]:hover:before,
.css-tips[data-title]:hover:after {
visibility: visible;
transform: translate(-50%, -10px);
opacity: 1;
}
复制代码
效果以下:
接下来咱们聊聊极端场景,及题目中提到的边界问题。
当这个按钮出如今屏幕顶端的时候,若是气泡依然是从顶部出现,很明显将会部分或者彻底不可见。解决这个问题,我想到的方案是给气泡添加方向属性,经过从不一样方向出现来避免对应的边界。
咱们能够为元素添加一个 data-title-dir
属性,默认从上方弹出气泡,若是设置方向,则从指定方向弹出:
属性 | 描述 | 使用 |
---|---|---|
data-title-dir |
规定提示的方向,能够取值top(默认)、right、bottom、left | <span class="css-tips" data-title="删除" data-title-dir="right">提示右</span> |
实现原理上面已经分析过了,就再也不赘述:
/* right */
.css-tips[data-title][data-title-dir="right"]:before,
.css-tips[data-title][data-title-dir="right"]:after{
left: 100%;
top: 50%;
bottom: auto;
transform: translate(20px, -50%);
}
.css-tips[data-title][data-title-dir="right"]:after {
margin: 0;
margin-left: -12px;
border-color: transparent;
border-right-color: currentColor;
}
.css-tips[data-title][data-title-dir="right"]:hover:before,
.css-tips[data-title][data-title-dir="right"]:hover:after {
visibility: visible;
transform: translate(10px, -50%);
opacity: 1;
}
/* bottom */
.css-tips[data-title][data-title-dir="bottom"]:before,
.css-tips[data-title][data-title-dir="bottom"]:after{
left: 50%;
top: 100%;
bottom: auto;
transform: translate(-50%, 20px);
}
.css-tips[data-title][data-title-dir="bottom"]:after {
margin: 0;
margin-top: -12px;
border-color: transparent;
border-bottom-color: currentColor;
}
.css-tips[data-title][data-title-dir="bottom"]:hover:before,
.css-tips[data-title][data-title-dir="bottom"]:hover:after {
visibility: visible;
transform: translate(-50%, 10px);
opacity: 1;
}
/* left */
.css-tips[data-title][data-title-dir="left"]:before,
.css-tips[data-title][data-title-dir="left"]:after{
left: auto;
right: 100%;
top: 50%;
bottom: auto;
transform: translate(-20px, -50%);
}
.css-tips[data-title][data-title-dir="left"]:after {
margin: 0;
margin-right: -12px;
border-color: transparent;
border-left-color: currentColor;
}
.css-tips[data-title][data-title-dir="left"]:hover:before,
.css-tips[data-title][data-title-dir="left"]:hover:after {
visibility: visible;
transform: translate(-10px, -50%);
opacity: 1;
}
复制代码
效果以下:
还有一个场景就是提示文本过长。这个问题咱们也能够像边界问题那样给元素添加一个 data-title-muti
属性来指定是否换行:
属性 | 描述 | 使用 |
---|---|---|
data-title-muti |
适用于提示文本较多的状况,自动换行 | <span class="css-tips" data-title="删除" data-title-muti>提示</span> |
/* muti */
.css-tips[data-title][data-title-muti]:before {
width: 150px;
white-space: normal;
}
复制代码
效果如图:
对于这个需求,其实还能够继续优化扩展,好比添加状态,不一样状态有不一样的颜色来提示,好比结合 js 添加回调等等。
固然这些功能早就有不少开源库作了,并且作得很好很强壮,因此在平常开发中,便没必要在重复造轮子了,做为学习了解原理和设计思路能够,但切记不要舍本逐末。