CSS 小测 - 02

说在前面

本篇是张鑫旭老师的 CSS基础测试2 的阅后笔记。(另外感谢 XboxYan 的解答,逻辑很是清晰)javascript

题目

话很少说,先上题,HTML 以下:css

<a href="javascript:" class="icon-delete css-tips" data-title="删除" role="button" >
  删除
</a>
复制代码

现需实现以下效果:html

img-00

要求:java

  • 纯 css 实现
  • 考虑边界状况

思路

分析完题目以后,能够看到,出题者很贴心的给了 a 标签两个 class:git

  • icon-delete
  • css-tips

意图很明显,icon-delete 用于实现把文字替换成图标的功能,而 css-tips 用于实现气泡提示效果。 那么首先把比较简单的功能完成。github

icon-delete

这里能够经过把字体大小设置为 0,而后经过设置背景的方式来完成图标化:学习

.icon-delete{
    display: block;
    width: 30px;
    height: 30px;
    font-size: 0px;
    background: url(./del.png) no-repeat center;
    background-size: cover;
}
复制代码

这样就完成了这个简单的功能,效果以下:测试

img-01

css-tips

这个功能较为复杂,咱们先不考虑各类场景,只单独的把这个气泡提示作出来。字体

给元素附加挂件的效果,这里咱们能够经过 beforeafter 伪类来作。优化

因为气泡浮于元素上方,因此这里第一反应是要用到绝对定位:

.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;
}
复制代码

到这里,咱们成功的将 beforeafter 定位到了按钮的正上方:

img-02

接下来分别对 beforeafter 进行调整,这里咱们使用 before 来作为装填文字的容器,使用 after 做为气泡下方的箭头。

before

首先因为咱们并不知道提示文字长度,因此没必要设置高宽。 那么 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;
  }
复制代码

效果以下:

img-03

after

上图能够看到,在气泡中间有一块黑色的遮挡,这个就是 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;
}
复制代码

img-04

能够看到,四个角恰好是四个三角形,那么须要什么样的三角形,将其余的 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;
  }

复制代码

效果如图:

img-05

接下来须要作的就是在 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;
  }
复制代码

效果以下:

img-06

优化

优化要从两个方面提及:

  • 适应极端场景
  • 体验优化

(其实说白了都是体验优化)

体验优化

咱们先来讲说体验优化,能够看到上面最后的动图效果很是僵硬,而且鼠标移动过来就马上出现气泡,假设如今有一个这样的场景:

一个表格,每一行均可以删除,用户从下往上移动鼠标,想要删除第 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;
  }
复制代码

效果以下:

img-07

到这里其实气泡也显得并不那么生硬了,固然若是愿意的话能够再增长一个过渡,显得更加灵动:

.css-tips[data-title]:hover:before,
.css-tips[data-title]:hover:after {
    visibility: visible;
    transform: translate(-50%, -10px);
    opacity: 1;
  }
复制代码

效果以下:

img-08

适应极端场景

接下来咱们聊聊极端场景,及题目中提到的边界问题。

当这个按钮出如今屏幕顶端的时候,若是气泡依然是从顶部出现,很明显将会部分或者彻底不可见。解决这个问题,我想到的方案是给气泡添加方向属性,经过从不一样方向出现来避免对应的边界。

咱们能够为元素添加一个 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;
}
复制代码

效果以下:

img-09

还有一个场景就是提示文本过长。这个问题咱们也能够像边界问题那样给元素添加一个 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;
}
复制代码

效果如图:

img-10

结束语

对于这个需求,其实还能够继续优化扩展,好比添加状态,不一样状态有不一样的颜色来提示,好比结合 js 添加回调等等。

固然这些功能早就有不少开源库作了,并且作得很好很强壮,因此在平常开发中,便没必要在重复造轮子了,做为学习了解原理和设计思路能够,但切记不要舍本逐末。

这里是在线 demo

相关文章
相关标签/搜索