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

相關文章
相關標籤/搜索