當你的用戶需要一些額外的上下文來放置圖標,或者當他們需要一些保證來點擊按鈕,或者可能是一個彩蛋的標題來搭配一個圖片時,工具提示是一個很好的方法來增強使用者介面。現在讓我們來製作一些動畫提示工具,只使用HTML和CSS。
(推薦教學:CSS教學)
示範
以下是我們的工作目標:
主要目標是擁有一種新增工具提示的簡單方法,因此我們將透過新增自訂tooltip
屬性來做到這一點:
<span tooltip="message">visible text or icon, etc.</span><br/>
關於可訪問性和功能的說明
#如果您正在尋找508相容的工具提示,或者需要更聰明的工具提示,支援容器衝突檢測和/或支援HTML內容與純文本,那麼有許多使用第三方腳本的解決方案可以滿足您的這些需求。
讓我們設定幾個預期
#不需要JavaScript
我們將會使用屬性選擇器(而不是類別名稱),以及CSS內建的模式匹配
加到現有的DOM元素(你的標籤不需要新的元素)
程式碼範例中是沒有前綴的(如有需要,為你的目標瀏覽器加上供應商前綴)
假設透過mouseover/hover 來觸發提示框
只是純文字提示框(HTML,圖片等等都不支援)
當喚起提示框時,有巧妙的動畫
下面我們開始
我們還要先處理一個問題,是關於"不需要額外標籤"的。畢竟,這很巧妙。我們的提示框真的不需要額外的DOM元素,因為它們完全是基於偽元素的(::before
和 ::after
),我們可以透過CSS來控制。
如果你已經在其它樣式集中使用了一個元素的偽元素,又希望在這個元素是加一個提示框,那麼你可能需要稍稍重構。
提示框
還有一個警告:CSS定位。為了提示框正常運作,它們的父元素(我們把提示方塊加在它後面)需要是
position: relative
,或
position: absolute
,或
#position: fixed
#基本上,什麼都行,只要不是 position: static — 這是瀏覽器賦給幾乎所有元素的預設定位模式。提示框是絕對定位的,所以它們需要知道它們的絕對值在什麼邊界內是有意義的。
預設的定位指令 static 不會宣告它的邊界,也不會給我們的提示方塊以情境來進行相對定位。所以提示框會使用之後,最近的,有聲明邊界的父元素。
你需要決定哪個位置指令最適合你如何使用工具提示。本教程假設位置:相對於父元素。如果您的UI依賴一個絕對定位的元素,那麼可能還需要一些重組(額外的標記)來在該元素上部署工具提示。
屬性選擇器:快速回顧
大多數CSS規則印像中都是用類別名稱寫的,例如 #.this -thing
,但是CSS有幾個類型的選擇器。我們巧妙的提示框打算使用屬性選擇器-也就是方括號表示法。
[foo] {<br/> background: rgba(0, 0, 0, 0.8);<br/> color: #fff;<br/>}<br/>
當瀏覽器看到諸如此類的東西時:
<span foo>Check it out!</span><br/>
瀏覽器會知道,它需要應用 [foo]
規則了,因為 427924e0bc1c500e0479e017d951eadf
標籤有一個叫做 foo
的屬性。在這個例子中,span
本身會有一個半透明的黑色背景,以及白色文字。
HTML元素有著各種各樣的內建屬性,但是我們也可以給出我們自己的屬性。例如 foo ,又或者是 tooltip 。預設情況下,HTML不知道這些東西是什麼意思,但有了CSS,我們可以告訴HTML這些自訂屬性是什麼意思。
為什麼要用屬性選擇器?
#我们后面会使用属性选择器,主要是出于侧重分离的目的。使用属性而不是类名,并不会让我们在详细程度上获得更多益处,类和属性在详细程度上是相同的。 然而,通过使用属性,我们可以把我们的内容放在一块儿,因为HTML属性可以有值,而类名没有值。
在这个例子的代码中,来权衡一下类名 .tooltip
对比属性 [tooltip]
。类名是 [class]
属性的值中的一个,而tooltip
属性可以存放一个值,它就是我们要显示的文字。
<span class="tooltip another-classname">lorem ipsum</span><br/><span tooltip="sit dolar amet">lorem ipsum</span><br/>
使用提示框
我们的提示框会使用两种不同的属性:
tooltip
: 这个属性存放了提示框的内容(一个纯文本字符串)
flow:
可选;这个属性允许我们控制如何显示提示框。我们可以支持很多方位,但是我们会覆盖4各常用方位:上,左,右,下
1. 相对性
这是用在提示框的父元素上的。让我们来给定一个定位指令,这样提示框的组成部分(即::before
和 ::after
伪元素)的绝对定位就可以以父元素做参照进行定位,而不是以整个页面或祖父元素或DOM树上方的其它外围元素作为参照进行定位。
[tooltip] {<br/> position: relative;<br/>}<br/>
2. 伪元素准备
在这里,我们要对 ::before
和 ::after
设置常用属性。content
属性是真正让伪元素工作的属性,不过我们稍后再讨论它。
[tooltip]::before,<br/>[tooltip]::after {<br/> line-height: 1;<br/> user-select: none;<br/> pointer-events: none;<br/> position: absolute;<br/> display: none;<br/> opacity: 0;<br/> <br/> /* opinions */<br/> text-transform: none; <br/> font-size: .9em;<br/>}<br/>
3、Dink
它是一个尖尖的小三角形,通过指向它的调用者,为提示框提供对话气泡的感觉。 注意到我们在边界颜色这一块,使用了 tranparent
;由于上色要根据提示框的 flow
值来,所以之后再加上颜色。
[tooltip]::before {<br/> content: '';<br/> z-index: 1001;<br/> border: 5px solid transparent;<br/>}<br/>
content: '';声明中的值是一个空字符串,这并不是笔误。字符串里面,我们不想要任何东西,但是我们需要这个属性,使得伪元素得以存在。
为了生成一个三角形,我们定义了一个实现边框,在空的盒子(没有内容)上加了一些厚度,而不设定盒子的宽度和高度,仅仅对盒子的每一条边都给一个边框颜色。
4、气泡
这里是重点了。注意内容:attr(tooltip)部分说:“此伪元素应使用tooltip属性的值作为其内容。”这就是为什么对类名使用属性是如此之好!
[tooltip]::after {<br/> content: attr(tooltip); /* magic! */<br/> z-index: 1000;<br/> <br/> /* most of the rest of this is opinion */<br/> font-family: Helvetica, sans-serif;<br/> text-align: center;<br/> <br/> /* <br/> Let the content set the size of the tooltips <br/> but this will also keep them from being obnoxious<br/> */<br/> min-width: 3em;<br/> max-width: 21em;<br/> white-space: nowrap;<br/> overflow: hidden;<br/> text-overflow: ellipsis;<br/> <br/> /* visible design of the tooltip bubbles */<br/> padding: 1ch 1.5ch;<br/> border-radius: .3ch;<br/> box-shadow: 0 1em 2em -.5em rgba(0, 0, 0, 0.35);<br/> background: #333;<br/> color: #fff;<br/>}<br/>
请注意,dink和气泡的z-index
值。 这些是任意值,但请记住,z索引值是相对的。 含义:z-index
为3的元素内部的z-index
值为1001只是意味着1001元素将是该z-index
:3容器中最顶层的元素。
气泡的z-index
应比Dink的z-index
至少降低1步。 如果它等于或高于该dink,那么如果您的工具提示使用了框阴影,则最终会在dink上产生不一致的着色效果。
5、交互作用
我们的提示框是通过把鼠标移动到带提示框的元素上面,来激活的。差不多是这样。
[tooltip]:hover::before,<br/>[tooltip]:hover::after {<br/> display: block;<br/>}<br/>
如果您在第2步中回顾我们的样式块,应该会看到我们使用了opacity:0;
连同显示:无; 用于我们的工具提示部分。 我们这样做是为了在显示和隐藏工具提示时可以使用CSS动画效果。
display属性是不能做成动画的,但是opacity属性可以!我们留到最后来处理动画的问题。如果你对动画提示框没兴趣,只要把第2步中的 opacity: 0;
删掉,无视第7步即可。
最后一件要应用到所有提示框上的是,如果提示框没有内容,能有一个方法来抑制提示框。如果你使用某种动态系统(Vue.js, Angular, 或者 React, PHP等等)来生成提示框的话,我们就不需要笨笨的空白气泡了!
/* don't show empty tooltips */<br/>[tooltip='']::before,<br/>[tooltip='']::after {<br/> display: none !important;<br/>}<br/>
6、流控制
这一步会变得更加复杂,因为我们会使用一些不那么常见的选择器,来帮助我们的提示框基于 flow 值(或没有flow属性)来确定位置。
在我们写样式之前,让我们看看将要用到一些选择器模式。
[tooltip]:not([flow])::before,<br/>[tooltip][flow^="up"]::before {<br/> /* ...<br/> properties: values<br/> ... */<br/>}<br/>
这是在告诉浏览器:“对于所有带有 tooltip
属性来说,其中没有 flow 属性的元素,或者有flow
元素,但它的值是以'up'开头的:将这些样式套用到这类元素的::before
伪元素上。”
我们在这里使用了一个模式,这样一来,这些东西可以扩展到其它流上,而步需要重复这么多的CSS。这个模式 flow^="up"
使用了 ^=
(开头)匹配符。 如果你想增加其它流控制的话,通过这个模式,也可以将样式应用在up-right
和 up-left
方向上(代码中)。
Up (default):
/* ONLY the ::before */<br/>[tooltip]:not([flow])::before,<br/>[tooltip][flow^="up"]::before {<br/> bottom: 100%;<br/> border-bottom-width: 0;<br/> border-top-color: #333;<br/>}<br/> <br/>/* ONLY the ::after */<br/>[tooltip]:not([flow])::after,<br/>[tooltip][flow^="up"]::after {<br/> bottom: calc(100% + 5px);<br/>}<br/> <br/>/* Both ::before & ::after */<br/>[tooltip]:not([flow])::before,<br/>[tooltip]:not([flow])::after,<br/>[tooltip][flow^="up"]::before,<br/>[tooltip][flow^="up"]::after {<br/> left: 50%;<br/> transform: translate(-50%, -.5em);<br/>}<br/>
Down:
[tooltip][flow^="down"]::before {<br/> top: 100%;<br/> border-top-width: 0;<br/> border-bottom-color: #333;<br/>}<br/> <br/>[tooltip][flow^="down"]::after {<br/> top: calc(100% + 5px);<br/>}<br/> <br/>[tooltip][flow^="down"]::before,<br/>[tooltip][flow^="down"]::after {<br/> left: 50%;<br/> transform: translate(-50%, .5em);<br/>}<br/>
Left:
[tooltip][flow^="left"]::before {<br/> top: 50%;<br/> border-right-width: 0;<br/> border-left-color: #333;<br/> left: calc(0em - 5px);<br/> transform: translate(-.5em, -50%);<br/>}<br/> <br/>[tooltip][flow^="left"]::after {<br/> top: 50%;<br/> right: calc(100% + 5px);<br/> transform: translate(-.5em, -50%);<br/>}<br/>
Right:
[tooltip][flow^="right"]::before {<br/> top: 50%;<br/> border-left-width: 0;<br/> border-right-color: #333;<br/> right: calc(0em - 5px);<br/> transform: translate(.5em, -50%);<br/>}<br/> <br/>[tooltip][flow^="right"]::after {<br/> top: 50%;<br/> left: calc(100% + 5px);<br/> transform: translate(.5em, -50%);<br/>}<br/>
7、对所有事物进行动画处理
动画是很神奇的。动画可以做到:
让用户感觉舒服
让用户感受到你的用户界面的空间感
注意到该看到的东西
让用户界面中本来非黑即白的生硬效果变得柔和
我们的提示框属于最后那一种。如果仅仅是让一个文字泡泡出现然后突然消失,效果是不令人满意的,我们可以让它更柔和一些。
@keyframes
我们需要两个关键帧 (@keyframe
) 动画。向上/向下提示框要用到tooltips-vert
关键帧,而向左/向右提示框使用tooltips-horz
关键帧。 注意,在这些关键帧中,我们只定义了提示框所需的终止状态。
我们并不需要知道它们从何处来 (提示框本身就有状态信息)。我们只想控制它们要到哪儿去。
@keyframes tooltips-vert {<br/> to {<br/> opacity: .9;<br/> transform: translate(-50%, 0);<br/> }<br/>}<br/> <br/>@keyframes tooltips-horz {<br/> to {<br/> opacity: .9;<br/> transform: translate(0, -50%);<br/> }<br/>}<br/>
现在,当用户将鼠标悬停在触发元素(带有[tooltip]
属性的元素)上时,我们需要将这些关键帧应用于工具提示。由于我们正在使用各种流来控制工具提示的显示方式,所以我们需要在样式中确定这些可能性。
使用:hover将控制传递给动画
[tooltip]:not([flow]):hover::before,<br/>[tooltip]:not([flow]):hover::after,<br/>[tooltip][flow^="up"]:hover::before,<br/>[tooltip][flow^="up"]:hover::after,<br/>[tooltip][flow^="down"]:hover::before,<br/>[tooltip][flow^="down"]:hover::after {<br/> animation: <br/> tooltips-vert <br/> 300ms <br/> ease-out<br/> forwards;<br/>}<br/> <br/>[tooltip][flow^="left"]:hover::before,<br/>[tooltip][flow^="left"]:hover::after,<br/>[tooltip][flow^="right"]:hover::before,<br/>[tooltip][flow^="right"]:hover::after {<br/> animation: <br/> tooltips-horz <br/> 300ms <br/> ease-out <br/> forwards;<br/>}<br/>
我们不能对display
属性进行动画,但是可以通过操作opacity
属性,在提示框上加上淡入效果。我们也可以动画transform
属性,它可以给提示框加上微妙的动作,触发的元素就像飞入某点的一样。
主要forward
关键词在动画的声明中,这告诉动画当完成时不重置,而是继续停留在结束。
效果如下:
更多编程相关知识,请访问:编程入门!!
以上是使用HTML+CSS製作一些動畫提示工具的詳細內容。更多資訊請關注PHP中文網其他相關文章!