zhangxinxu/quiz

CSS基础测试2

Opened this issue · 13 comments

本期小测题目如下图:

完全CSS实现,尝试考虑一些边界场景,以及其它一些可以对体验有帮助的处理。

大家的CSS代码注意顶边缩进,github自带代码高亮,可以使用下面的格式:

```css
/* 你的CSS代码在这里 */
```
.icon-delete {
    margin-top: 2em;
    display: inline-block;
    display: flex;
    flex-wrap: nowrap;
    max-width: 2em; 
    position: relative;
  }
  .icon-delete::before {
    display: inline-block;
    visibility: hidden;
    content: attr(data-title);
    background: #000;
    color: white;
    max-width: 2em;
    white-space: nowrap;
    border-radius: 5px;
    padding: 4px;
    position: absolute;
    top: -2em;
    left: 50%;
    transform: translateX(-50%)
  }
  .icon-delete::after {
    display: inline-block;
    visibility: hidden;
    content: '';
    width: 0;
    height: 0;
    border: .5em solid;
    border-color: #000 transparent transparent;
    position: absolute;
    top: calc(-0.5em + 4px);
    left: 50%;
    transform: translateX(-50%)
  }
  a:hover::before, a:hover::after {
    visibility: visible;
  }

绞尽脑汁也没想到怎么用 css 去做边界的问题.....

body{
    padding: 30px;
}
.icon-delete::after{
    content:"\27F0";
    font-size: initial;
}
.css-tips{
    position: relative;
    font-size: 0;
    cursor: pointer;
}
.css-tips:hover::before{
    content:attr(data-title);
    position: absolute;
    margin-left: 50%;
    transform: translate(-50%,-2.5em);
    padding: 4px 4px 10px;
    color: #fff;
    font-size: 12px;
    white-space: nowrap;
    background: #000;
    clip-path: 
        polygon(
            0 0,
            100% 0, 
            100% calc(100% - 6px), 
            calc(50% + 4px ) calc(100% - 6px),
            50% 100%,
            calc(50% - 4px ) calc(100% - 6px),
            0  calc(100% - 6px)
        );
}
.css-tips:hover::before {
    content: attr(data-title);
    position: absolute;
    transform: translateY(-100%) translateY(-0.3em) translateX(-0.5em);
    width: 2em;
    padding: 0.2em 0.5em;
    border-radius:0.2em;
    background: #000;
    color: #fff;
}
.css-tips:hover::after {
    content: '';
    position: absolute;
    transform: translateY(-50%) translateX(-1.5em);
    border: 0.5em solid;
    border-color: #000 transparent transparent transparent;
}
.css-tips{
    position: relative;
}

目前归类了如下几种场景(可补充)

  1. 方向(上右下左)
  2. 多文本
  3. 类型(警示,温馨,危险)
属性 描述 用法
data-title-dir 规定提示的方向,可以取值top(默认)、rightbottomleft <span class="css-tips" data-title="删除删除删除" data-title-dir="up">提示上</span>
data-title-muti 适用于提示文本较多的情况,自动换行 <span class="css-tips" data-title="删除删除删除删除删除删除删除删除删除" data-title-dir="right" data-title-muti>多行提示</span>
data-title-type 选择提示的类型,即不同的背景颜色,默认为暗灰色,可以取值successerrorwarn <span class="css-tips" data-title="删除删除删除删除" data-title-type="warn">警告提示</span>

以上不同属性可以组合使用

<span class="css-tips" 
    data-title="删除删除删除删除删除删除删除删除删除" 
    data-title-dir="right" 
    data-title-type="warn"
    data-title-muti
>
    多行提示
</span>

源码

[data-title] {
    position: relative;
    overflow: visible;
}

.css-tips[data-title]:before,
.css-tips[data-title]:after {
    display: block;
    position: absolute;
    z-index: 1;
    left: 50%;
    bottom: 100%;
    transform: translate(-50%, -20px);
    opacity: 0;
    transition: .15s .15s;
    color: #373c42;
    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;
    transform: translate(-50%, -10px);
    opacity: 1;
}

/* 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;
}

/* muti */
.css-tips[data-title][data-title-muti]:before {
    width: 150px;
    white-space: normal;
}

/* success */
.css-tips[data-title][data-title-type="success"]:before {
    background-color: #52c41a;
}
.css-tips[data-title][data-title-type="success"]:after {
    color:#52c41a;
}
/* error */
.css-tips[data-title][data-title-type="error"]:before {
    background-color: #f5222d;
}
.css-tips[data-title][data-title-type="error"]:after {
    color:#f5222d;
}
/* warn */
.css-tips[data-title][data-title-type="warn"]:before {
    background-color: #faad14;
}
.css-tips[data-title][data-title-type="warn"]:after {
    color:#faad14;
}

预览

image

在线demo

.css-tips {
  position: relative;

  cursor: pointer;

  &:hover {
    &::before {
      position: absolute;
      top: -25px;

      font-size: 12px;

      box-sizing: border-box;
      width: max-content;
      height: auto;
      min-height: 20px;
      padding: 0 5px;

      content: attr(data-title);

      color: #fff;
      border-radius: 2px;
      background-color: rgba(0, 0, 0, 1);
    }
    &::after {
      position: absolute;
      top: -5px;
      left: 50%;

      width: 0;
      height: 0;

      content: ' ';
      transform: translateX(-50%);

      border-top: 3px solid rgba(0, 0, 0, 1);
      border-right: 3px solid transparent;
      border-left: 3px solid transparent;
    }
  }
}
body{
  margin: 0;
}
a{
  position: relative;
  text-decoration: none;
  width: 1em;
  display: inline-block;
  /*用margin来限制边界,确报提示框不会超出视野*/
  margin: 2em 1em;
}
a::before{
  content: "";
  width: 0;
  border-style: solid;
  border-width: 1em 0.5em 0 0.5em;
  border-color: #000 transparent transparent transparent;
  position: absolute;
  top: -1em;
  display: none; 
}
a::after{
  content: attr(data-title);
  position: absolute;
  top: -2em;
  left: -0.9em;
  word-break: keep-all;
  background-color: #000;
  padding: 0.2em 0.4em;
  color: #fff;
  border-radius: 0.2em;
  line-height: 1;
  display: none; 
}
a:hover::before,a:hover::after{
  display: block;
}

tim 20190131160258

.icon-delete {
    display: inline-block;
    background: url(https://i.loli.net/2019/01/31/5c529425d2a92.png)  0 0/contain no-repeat;
    text-indent: -9999px;
}

.css-tips:hover::before, .css-tips:hover::after {
    position: absolute;
    left: 50%;
    bottom: 100%;
}

.css-tips:hover::before {
    content: attr(data-title);
    padding: .2em .5em;
    text-indent: 0;
    border-radius: .2em;
    background: #000;
    white-space: nowrap;
    color: #fff;
    transform: translate(-50%, -.4em);
}
.css-tips:hover::after {
    content: '';
    transform: translate(-50%, .35em);
    border: 0.5em solid;
    border-color: #000 transparent transparent transparent;
}
.css-tips{
    position: relative;
    font-size: 16px;
}
drify commented

楼上一些回复忘了隐藏文字的问题,不过出题时保留「删除」二字的必要性何在呢?如果为了 accessibility ,屏幕阅读器应该会读出 <a> 标签的 title 属性的(参考知乎回答),写在那里会方便处理一些。

demo: JSFiddle

/* 一个图标字体,「删」字是图标,「除」字是零宽度字符 */
@font-face {
    font-family: shanchu;
    src: url('data:application/font-woff;base64,d09GRgABAAAAAAT8AA4AAAAABxgAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAABGRlRNAAAE4AAAABwAAAAchpT840dERUYAAATIAAAAGAAAABwAFQAUT1MvMgAAAbgAAABLAAAAYLJNCARjbWFwAAACGAAAAEYAAAFK2r0Rm2N2dCAAAAJgAAAABAAAAAQAOwRvZ2FzcAAABMAAAAAIAAAACP//AANnbHlmAAACcAAAASIAAAGEagP31WhlYWQAAAFEAAAAMQAAADYVj60EaGhlYQAAAXgAAAAdAAAAJAujBQZobXR4AAACBAAAABQAAAAUCmAAO2xvY2EAAAJkAAAADAAAAAwA7gEabWF4cAAAAZgAAAAfAAAAIABNAJluYW1lAAADlAAAAR0AAAH7nk+ALXBvc3QAAAS0AAAADAAAACAAAwAAeJxjYGRgYADi3byprfH8Nl8ZuNkZQOBGhcYNCG2tz8Dwv4EVCIFcDgYmkCgAGkkKAwAAAHicY2BkYGBt+N/AsJC1gYEBxGZgZEAFrABkwAO3AAAAeJxjYGRgYGBlyGBgYwABJiBmZACJOTDogQQADlgA5wB4nGNgYW1gnMDAysDA0sPyjIGB4ReEZo5hiGQ8z8DAxMDKzAAHHAgmQ0CaawrDgSCFaSlsDP8ZGBayNjA0AIUZkZQoMDACAMDLDQAAAosAOwAAAAACVQAABYAAAAAAAAB4nGNgYGBmgGAZBkYGEHAB8hjBfBYGDSDNBqQZGZiCFKal/P/PwACh1z7OXABVDwSMbAxwDiMTkGBiQAWMDMMeAAA34Ao9AAAAOwRvAAAALAAsACwAwgDCeJyFkD1Lw1AUhs+5Nx+0Q8KNbcbW25K0INiSjzokllChg5QuBccSQXB06uCWP+HmXuiW4OBY8F+If8FfYBK9N3uRA4f3PjycFy4QiABIVzkABR0uc4RJXOgKfHu5pn7FBSUiQk4lViUudA3LuEDJfcaZwxmP8LO+x4f6VTn83EVKAAAawG+migET+jARLTfwCICso13gwA1ZMIvQs9V/3meiodNDn3tzRD5yR1zT1a50hDjkUhwO3GsMZj6/mkvP7qNYBCwjMaxm4YmclZlhUppQ06hSPE71dv3R1umTZaTbRXlcbFMpYrg012NMxmtziaFh0fPqKDlpzpzIVY++lSvbYcxRbnctQlovAperzfNuQ9+b9r0TBM7eEl/1B1oESgcAAHicdY6/SsNQGMXPbdMWl+Lq9oEOLTThJtWhXYsZHaR0FEKIycVyU24ToYuP5GP4MD6CkyfpdXBo4PL9vj855wCY4hMK5+8G954VJnjxPCC/ex7iFl+eA85/PI9wre48jzFRj7xUwRW7pP+rY0WvJ88D8qvnIVJ8eA44//Y8gqiB5zGm6gEb1DjgBAeDEhUaCGbIMWdNoBFjhQV5y52BxRuwqQ8nZ8qqkVk+l0THq4VsK2O5OvIq41XO2rKtMptXhGcUVG+x59axLcp2nxFSult6dtXxouhdI/oK1nz/9c6zJTOF/fvLh7S2TVq7spAk0rIW70taxmEcdhEvZ9vR1XFr+ixCzU416muXA7vCHU1tRes40lrLRalfgcNLWwAAAHicY2BmwAsAAH0ABAAAAAH//wACeJxjYGSAAB4GEQYWIM0ExIwQDAACywAqAAAAAQAAAADVpJjbAAAAANh4KNgAAAAA2Hg7Lw==') format('woff');
}

.icon-delete {
    font-family: shanchu;
    text-decoration: none;
    color: black;
}

.css-tips {
    position: relative;
}
.css-tips::before, .css-tips::after {
    position: absolute;
    display: block;
    z-index: 1;
}
.css-tips:hover::before {
    content: attr(data-title);
    font-family: sans-serif;
    font-size: 80%;
    color: white;
    background-color: black;
    white-space: nowrap;
    top: -3.5em;
    padding: 0.5em 0.8em;
    left: -1.25em;
    border-radius: 4px;
    line-height: 1.4;
}
.css-tips:hover::after {
    content: '';
    border: 0.5em solid transparent;
    border-top-color: black;
    top: -1em;
    left: 50%;
    margin-left: -0.5em;
}
.icon-delete{
        position: relative;
        display: inline-block;
        margin-top: 2em;
        font-size: 16px;
}
.css-tips::before{
        display: none;
        content: attr(data-title);
        position: absolute;
        top: -2em;
        left: 50%;
        padding: 0.3em;
        background-color: #000;
        color: white;
        white-space: nowrap;
        border-radius: 5px;
        transform: translateX(-50%);
}
 .css-tips::after{
        display: none;
        content: "";
        position: absolute;
        top: -0.2rem;
        left: 0;
        right: 0;
        width: 0;
        height: 0.8em;
        margin: auto;
        border: 0.4em solid transparent; 
        border-top-color: #000;
}
.css-tips:hover::before,
.css-tips:hover::after{
        display: block;
}
body{
      padding:20px;
}
.icon-delete{
      text-decoration: none;
      position: relative;
}
.css-tips::before{
     position: absolute;
     content: attr(data-title);
     border-radius: 6px;
     border: 1px solid black;
     text-align:center;
     width:42px;
     height:25px;
     color:white;
     background-color: black;
     top:-42px;
     left:-6px;
     font-size:10px;
     padding-top:6px;
     visibility: hidden;
     letter-spacing:2px;
}
.css-tips::after{
    visibility: hidden;
    position:absolute;
    content:"";
    border-width:5px;
    border-style:solid;
    border-color:black transparent transparent transparent;
    left:12px;
    top:-10px;
}
.css-tips:hover::after,.css-tips:hover::before{
    visibility:visible;
}
.icon-delete{
     position: relative;
     display:inline-block;
     width:16px;
     height: 16px;
     color:transparent;
     content: '';
     background: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAxklEQVQ4T+XTP0oDQRTH8c+SKlVuINglXbRNBI+R2KWwE7EQD5ALBAJB0qmN2OQSFmITDFgFUuUIgoVayMIKy7Czm5gyU83we+/7/sx7iR1PUuI/wlGmv+OiyDYPqOESjcywj8eC+wfG+E61POA4i/JQUVUP93gJAU1M8YyfEkgH11iEgPQ9wQrzCOAAJzj/08MmDjHDWwTQwgA3VYBDrINS2njdFNDFEl+5TE7xtEeAnZv47288wxU+I3NQxy3uYnOw9XL/AlB7OBGPcxK+AAAAAElFTkSuQmCC') no-repeat;
   }
   /* 上提示 */
   .css-tips:hover::after{
     position:absolute;
     top:-34px;
     left:50%;
     transform: translate(-50%,0);
     display:inline-block;
     padding:0 10px;
     height:24px;
     font-size:12px;
     color:#fff;
     text-align: center;
     line-height: 24px;
     border-radius: 3px;
     content:attr(data-title);
     white-space: nowrap;
     background: #000;
   }
   .css-tips:hover::before{
     display: inline-block;
     position:absolute;
     top:-10px;
     left:50%;
     transform: translate(-50%,0);
     width:0;
     height:0;
     content:'';
     border-width:5px 5px 0;
     border-style:solid;
     border-color:#000 transparent transparent;
   }
   /* 下提示 */
   .css-tips.bottom:hover::after{
     top:26px;
   }
   .css-tips.bottom:hover::before{
     top:21px;
     border-width:0 5px 5px;
     border-color:transparent transparent #000;
   }
   /* 左提示 */
   .css-tips.left:hover::after{
     top:50%;
     transform: translate(-100%,-50%);
     left:-10px;
   }
   .css-tips.left:hover::before{
     top:50%;
     transform: translate(0,-50%);
     left:-10px;
     border-width:5px 0 5px 5px;
     border-color:transparent transparent transparent #000;
   }
   /* 右提示 */
   .css-tips.right:hover::after{
     top:50%;
     transform: translate(0,-50%);
     left:26px;
   }
   .css-tips.right:hover::before{
     top:50%;
     transform: translate(0,-50%);
     left:21px;
     border-width:5px 5px 5px 0;
     border-color:transparent #000 transparent transparent;
   }
        .icon-delete{
            position: relative;
        }
        .icon-delete::before{
            visibility: hidden;
            content: attr(data-title);
            position: absolute;
            width: 2em;
            top: -3em;
            left: 50%;
            transform: translateX(-50%);
            font-size: 12px;
            padding: .5em .8em;
            border-radius: 3px;
            color: #fff;
            background: #000;
        }
        .icon-delete::after{
            visibility: hidden;
            position: absolute;
            top: -.45em;
            left: 50%;
            transform: translateX(-50%);
            width: 0;
            content:'';
            border-left: .3em solid transparent;
            border-right: .3em solid transparent;
            border-top: .3em solid #000;
        }
        .icon-delete:hover::before,
        .icon-delete:hover::after{
            visibility:visible;
        }
  1. 考虑各种字号场景,使用bottom定位,calc()或者margin-bottom微调位置;
  2. transform增加-ms-前缀,兼容IE9;
  3. 考虑边界场景,例如在浏览器上边缘,或者侧面时候;
  4. 考虑增加延迟显示,使用visibility+transition,或者pointer-events: none(渐进增强);
  5. 考虑键盘访问,增加:focus伪类显示。