如何使用CSS建立巧妙的動畫提示框

原文:https://webdesign.tutsplus.co...
原做:Jase Smith
翻譯:Stypstivecss

當你的用戶須要漂亮的圖標給出額外的文字信息時,亦或是當他們在點擊了按鈕以後須要確認本身沒點錯時,又或是帶圖片和字幕的復活節彩蛋,提示框是用來加強用戶界面的絕佳手段。如今,讓咱們來作幾個動畫提示框,沒有別的,只有HTML和CSS。html

樣例

這是咱們以後要作的:web

http://jsfiddle.net/kcschaefe...瀏覽器

在咱們沉浸在寫代碼的過程當中以前,讓咱們先來看看咱們的意圖是什麼。主要目的是爲了得到一種簡單的添加提示框的方法,這樣一來,咱們以後就可以經過增長一個自定義的 tooltip 屬性來作到這一點。post

<span tooltip="message">visible text or icon, etc.</span>

關於可訪問性和功能的記注

若是你在尋找兼容508的提示框,或者須要帶容器衝突偵測和/或HTML內容 vs 純文本的智能提示框,有許多實用第三方腳本的解決方案能知足你的要求。動畫

"用JavaScript來作徹底可訪問的交互組件是命令式的" - Sara Soueidan, 打造一個徹底可訪問的幫助提示框...比你想的要難this

這篇教程不會特意解決可訪問性的需求。你瞭解你的用戶,知道他們須要什麼,因此有關這方面,也要記得考慮他們的需求。spa

讓咱們設定幾個預期

  • 不須要JavaScript.net

  • 咱們將會使用屬性選擇器(而不是類名),以及CSS內建的模式匹配翻譯

  • 加到現有的DOM元素(你的標籤中不須要新的元素)

  • 代碼例子中是沒有前綴的(若有須要,爲你的目標瀏覽器加上供應商前綴)

  • 假設經過 mouseover/hover 來觸發提示框

  • 僅僅是純文本提示框(HTML,圖片等等都不支持)

  • 當喚起提示框時,有巧妙的動畫

好了,老司機要開車了!

哦,等等。咱們還要先處理一個問題,是關於"不須要額外標籤"的。畢竟,這很巧妙。 咱們的提示框真的不須要額外的DOM元素,由於它們徹底是基於僞元素的(::before::after),咱們能夠經過CSS來控制。

若是你已經在其它樣式集中使用了一個元素的僞元素,又但願在這個元素是加一個提示框,那麼你可能須要稍稍作一些重構。

沒什麼比得上來一場提示框盛會了!

等等。小壞蛋!還有一個警告:CSS定位。爲了提示框正常運做,它們的父元素(咱們把提示框添加在它後面)須要是

  • position: relative,或者

  • position: absolute,或

  • position: fixed

基本上,什麼都行,只要不是 position: static — 這是瀏覽器賦給幾乎全部元素的默認定位模式。提示框是絕對定位的,因此它們須要知道它們的絕對值在什麼邊界內是有意義的。 默認的定位指令 static 不會聲明它的邊界,也不會給咱們的提示框以上下文來進行相對定位。因此提示框會使用以後,最近的,有聲明邊界的父元素。

你還須要根據你如何使用提示框來決定哪一個定位指令最爲合適。這篇教程假設父元素是 postion: relative 若是你的UI依靠一個絕對定位的元素,那麼在那個元素上部署一個提示框,也會須要一些重構(額外的標籤)。

讓咱們開始吧。

屬性選擇器:快速回顧

大多數CSS規則印象中都是用類名寫的,好比 .this-thing ,可是CSS有幾個類型的選擇器。咱們巧妙的提示框打算使用屬性選擇器——也就是方括號表示法。

[foo] {
    background: rgba(0, 0, 0, 0.8);
    color: #fff;
}

當瀏覽器看到諸如此類的東西時:

<span foo>Check it out!</span>

瀏覽器會知道,它須要應用 [foo] 規則了,由於 <span> 標籤有一個叫作 foo 的屬性。在這個例子中,span自身會有一個半透明的黑色背景,以及白色文字。

HTML元素有着各類各樣的內置屬性,可是咱們也能夠給出咱們本身的屬性。好比 foo ,又或者是 tooltip 。默認狀況下,HTML不知道這些東西是什麼意思,可是有了CSS,咱們能夠告訴HTML這些自定義屬性是什麼意思。

爲何用屬性選擇器?

咱們後面會使用屬性選擇器,主要是出於側重分離的目的。使用屬性而不是類名,並不會讓咱們在詳細程度上得到更多益處,類和屬性在詳細程度上是相同的。 然而,經過使用屬性,咱們能夠把咱們的內容放在一起,由於HTML屬性能夠有值,而類名沒有值。

在這個例子的代碼中,來權衡一下類名 .tooltip 對比屬性 [tooltip] 。類名是 [class] 屬性的值中的一個,而tooltip屬性能夠存放一個值,它就是咱們要顯示的文字。

<span class="tooltip another-classname">lorem ipsum</span>
 
<span tooltip="sit dolar amet">lorem ipsum</span>

如今讓咱們來看看提示框鍊金術

咱們的提示框會使用兩種不一樣的屬性:

  • tooltip: 這個屬性存放了提示框的內容(一個純文本字符串)

  • flow: 可選;這個屬性容許咱們控制如何顯示提示框。咱們能夠支持不少方位,可是咱們會覆蓋4各經常使用方位:上,左,右,下

如今,讓咱們爲全部的提示框作好準備工做。步驟1-5的規則會應用到全部的提示框上,不管咱們給 flow 屬性什麼值。步驟6-7對於不一樣的 flow 值會有所區分。

1) 相對性

這是用在提示框的父元素上的。讓咱們來給定一個定位指令,這樣提示框的組成部分(即::before::after 僞元素)的絕對定位就能夠以父元素作參照進行定位,而不是以整個頁面或祖父元素或DOM樹上方的其它外圍元素做爲參照進行定位。

[tooltip] {
  position: relative;
}

2) 僞元素準備時間

是時候準備僞元素了。在這裏,咱們要對 ::before::after 設置經常使用屬性。content 屬性是真正讓僞元素工做的屬性,不過咱們稍後再討論它。

[tooltip]::before,
[tooltip]::after {
    line-height: 1;
    user-select: none;
    pointer-events: none;
    position: absolute;
    display: none;
    opacity: 0;
 
    /* opinions */
    text-transform: none; 
    font-size: .9em;
}

3) 丁克帽

我不知道丁克帽是否是說得通,我只是一直這麼叫它。它是一個尖尖的小三角形,經過指向它的調用者,爲提示框提供對話氣泡的感受。 注意到咱們在邊界顏色這一塊,使用了 tranparent ;因爲上色要根據提示框的 flow 值來,因此以後再加上顏色。

[tooltip]::before {
    content: '';
    z-index: 1001;
    border: 5px solid transparent;
}

content: '';聲明中的值是一個空字符串,這並非筆誤。字符串裏面,咱們不想要任何東西,可是咱們須要這個屬性,使得僞元素得以存在。

爲了生成一個三角形,咱們定義了一個實現邊框,在空的盒子(沒有內容)上加了一些厚度,而不設定盒子的寬度和高度,僅僅對盒子的每一條邊都給一個邊框顏色。

4) 氣泡!

這裏是重點了。注意到 content: attr(tooltip) 這一部分是說:「這個僞類應該使用 tooltip 屬性的值做爲這個僞類的內容。」這也是爲何使用屬性而不是類名會這麼讚的緣由。

[tooltip]::after {
    content: attr(tooltip); /* magic! */
    z-index: 1000;
     
    /* most of the rest of this is opinion */
    font-family: Helvetica, sans-serif;
    text-align: center;
     
    /* 
    Let the content set the size of the tooltips 
    but this will also keep them from being obnoxious
    */
    min-width: 3em;
    max-width: 21em;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
     
    /* visible design of the tooltip bubbles */
    padding: 1ch 1.5ch;
    border-radius: .3ch;
    box-shadow: 0 1em 2em -.5em rgba(0, 0, 0, 0.35);
    background: #333;
    color: #fff;
}

注意看丁克帽和睦泡的 z-index 值。這些值能夠是任意的。可是要記住,z-index 值是相對的。 解釋:一個z-index值爲1001的元素,在一個z-index爲3的元素內部。僅僅意味着,z-index: 3 容器內部,1001元素是最頂層的元素。

氣泡的z-index應該至少比丁克帽的z-index低一檔。若是它和丁克的同樣高,或更高的話,若是你提示框使用了 box-shadow 的話,結果在丁克帽上回獲得不一致的顏色效果。

5)交互動做

咱們的提示框是經過把鼠標移動到帶提示框的元素上面,來激活的。差很少是這樣。

[tooltip]:hover::before,
[tooltip]:hover::after {
    display: block;
}

若是你回顧在第2不中的樣式部分,你會看到咱們對提示框的組成部分,使用了 opacity: 0; 以及 display: none; 。咱們這麼作是爲了當提示框顯示和隱藏時,可使用CSS動畫效果。

display屬性是不能作成動畫的,可是opacity屬性能夠!咱們留到最後來處理動畫的問題。若是你對動畫提示框沒興趣,只要把第2步中的 opacity: 0; 刪掉,無視第7步便可。

最後一件要應用到全部提示框上的是,若是提示框沒有內容,能有一個方法來抑制提示框。若是你使用某種動態系統(Vue.js, Angular, 或者 React, PHP等等)來生成提示框的話,咱們就不須要笨笨的空白氣泡了!

/* don't show empty tooltips */
[tooltip='']::before,
[tooltip='']::after {
    display: none !important;
}

6) 流控制

這一步會變得更加複雜,由於咱們會使用一些不那麼常見的選擇器,來幫助咱們的提示框基於 flow 值(或沒有flow屬性)來肯定位置。

「奇怪的東西出如今了 Circle-K 的門口」 — Ted Theodore Logan

在咱們寫樣式以前,讓咱們看看將要用到一些選擇器模式。

[tooltip]:not([flow])::before,
[tooltip][flow^="up"]::before {
    /* ...
    properties: values
    ... */
}

這是在告訴瀏覽器:「對於全部帶有 tooltip 屬性來講,其中沒有 flow 屬性的元素,或者有flow元素,但它的值是以'up'開頭的:將這些樣式套用到這類元素的::before僞元素上。」

咱們在這裏使用了一個模式,這樣一來,這些東西能夠擴展到其它流上,而步須要重複這麼多的CSS。這個模式 flow^="up" 使用了 ^= (開頭)匹配符。 若是你想增長其它流控制的話,經過這個模式,也能夠將樣式應用在 up-right 和 up-left 方向上(代碼中)。咱們在這裏不會討論這些流控制,不過你能夠在CodePen上,我原來的提示框演示中看到如何使用它們。

如下是教程中所講到的4個流所對應的CSS代碼塊。

/* ONLY the ::before */
[tooltip]:not([flow])::before,
[tooltip][flow^="up"]::before {
    bottom: 100%;
    border-bottom-width: 0;
    border-top-color: #333;
}
 
/* ONLY the ::after */
[tooltip]:not([flow])::after,
[tooltip][flow^="up"]::after {
    bottom: calc(100% + 5px);
}
 
/* Both ::before & ::after */
[tooltip]:not([flow])::before,
[tooltip]:not([flow])::after,
[tooltip][flow^="up"]::before,
[tooltip][flow^="up"]::after {
    left: 50%;
    transform: translate(-50%, -.5em);
}

[tooltip][flow^="down"]::before {
    top: 100%;
    border-top-width: 0;
    border-bottom-color: #333;
}
 
[tooltip][flow^="down"]::after {
    top: calc(100% + 5px);
}
 
[tooltip][flow^="down"]::before,
[tooltip][flow^="down"]::after {
    left: 50%;
    transform: translate(-50%, .5em);
}

[tooltip][flow^="left"]::before {
    top: 50%;
    border-right-width: 0;
    border-left-color: #333;
    left: calc(0em - 5px);
    transform: translate(-.5em, -50%);
}
 
[tooltip][flow^="left"]::after {
    top: 50%;
    right: calc(100% + 5px);
    transform: translate(-.5em, -50%);
}

[tooltip][flow^="right"]::before {
    top: 50%;
    border-left-width: 0;
    border-right-color: #333;
    right: calc(0em - 5px);
    transform: translate(.5em, -50%);
}
 
[tooltip][flow^="right"]::after {
    top: 50%;
    left: calc(100% + 5px);
    transform: translate(.5em, -50%);
}

7) 讓一切都動起來

動畫是很神奇的。動畫能夠作到:

  • 讓用戶感受舒服

  • 讓用戶感覺到你的用戶界面的空間感

  • 注意到該看到的東西

  • 讓用戶界面中原本非黑即白的生硬效果變得柔和

咱們的提示框屬於最後那一種。若是僅僅是讓一個文字泡泡出現而後忽然消失,效果是不使人滿意的,咱們可讓它更柔和一些。

關鍵幀 (@keyframes)

咱們須要兩個關鍵幀 (@keyframe) 動畫。向上/向下提示框要用到tooltips-vert關鍵幀,而向左/向右提示框使用tooltips-horz關鍵幀。 注意,在這些關鍵幀中,咱們只定義了提示框所需的終止狀態。咱們並不須要知道它們從何處來 (提示框自己就有狀態信息)。咱們只想控制它們要到哪兒去。

@keyframes tooltips-vert {
  to {
    opacity: .9;
    transform: translate(-50%, 0);
  }
}
 
@keyframes tooltips-horz {
  to {
    opacity: .9;
    transform: translate(0, -50%);
  }
}

如今,當一個用戶的鼠標移到觸發元素 (具備[tooltip]屬性的元素) 上時,咱們須要將這些關鍵幀應用到提示框上。由於咱們採用了不一樣的流來控制提示框的顯示方式,咱們須要在樣式中對它們進行定義。

使用:hover將控制傳遞給動畫

[tooltip]:not([flow]):hover::before,
[tooltip]:not([flow]):hover::after,
[tooltip][flow^="up"]:hover::before,
[tooltip][flow^="up"]:hover::after,
[tooltip][flow^="down"]:hover::before,
[tooltip][flow^="down"]:hover::after {
    animation: 
        tooltips-vert 
        300ms 
        ease-out
        forwards;
}
 
[tooltip][flow^="left"]:hover::before,
[tooltip][flow^="left"]:hover::after,
[tooltip][flow^="right"]:hover::before,
[tooltip][flow^="right"]:hover::after {
    animation: 
        tooltips-horz 
        300ms 
        ease-out 
        forwards;
}

咱們不能對display屬性進行動畫,可是能夠經過操做opacity屬性,在提示框上加上淡入效果。咱們也能夠動畫transform屬性,它能夠給提示框加上微妙的動做,觸發的元素就像飛入某點的同樣。

主要forward關鍵詞在動畫的聲明中,這告訴動畫當完成時不重置,而是繼續停留在結束。

結論

棒極了!咱們在這個教程裏已經覆蓋了不少,一堆提示框效果。

http://jsfiddle.net/kcschaefe...

咱們僅僅摸索了用css作提示框的表面。好好享受它們,繼續試驗,調製出你本身的方子!

相關文章
相關標籤/搜索