在 mac 文件管理中有這樣一個小細節。
- 當文件名不超過一行時,完整顯示,此時鼠標放上去無任何提示
- 當文件名超過一行時,出現省略號,此時鼠標放上去提示顯示完整文件名
一個很微妙但非常人性化的細節(ps.都能完全看見也就不需要提示了)。其實這類效果在 web 中,通過簡單的 css 也能輕易實現的。下面就來看看吧~
一、CSS 實現思路
相信大家都知道 title 這個屬性,原生的提示就用這個了,可以說從上古世紀就開始支持,下面是 MDN 上關于這個屬性的介紹
title 全局屬性 包含了表示咨詢信息文本,和它屬于的元素相關。這個信息通常存在,但絕不必要,作為提示信息展示給用戶
用法也非常簡單
<p class="txt" title="這是absolute">元素會被移出正常文檔流,并不為元素預留空間,通過指定元素相對于最近的非 static 定位祖先元素的偏移,來確定元素位置。絕對定位的元素可以設置外邊距(margins),且不會與其他邊距合并。
</p>
這里 title 的表現樣式還有停留時間與操作系統和瀏覽器有關,也不可修改
現在問題來了,title 屬性是預先添加的,并且無法通過樣式來控制是否顯示,那么,CSS 如何做到動態處理呢?接著往下看
雖然 CSS 無法動態去改變 title 屬性,換個思路,假如有兩份相同的文本,其中一份是帶有 title 屬性的,比如
<p class="wrap">
<span class="txt">元素會被移出正常文檔流,并不為元素預留</span>
<span class="title" title="元素會被移出正常文檔流,并不為元素預留">元素會被移出正常文檔流,并不為元素預留</span>
</p>
為了方便演示,這里給帶有 title 屬性的文本加上背景色,然后暫且稱為 文本A 和 文本B 吧(以下適用),如下所示
現在只需要在單行文本的時候展示 文本A ,多行文本的時候展示 文本B,就可以實現我們想要的功能了。
那么,如何判斷文本是否超出一行呢?
二、多行文本判斷
首先,當文本超出一行時,高度必然會發生變化(),假設行高為 1.5,那么1行文本就是 1.5em,2行就是 3em,依次類推...
但是,如果我們限制A的最大高度為兩行,那么一行和多行不就區分開了嗎(單行高度是1.5em,多行高度是3em)
.txt{
display: block;
max-height: 3em;/*最大高度為2行*/
}
現在關鍵的一步來了,把文本B 往上移動2行的距離,這里用相對定位實現(margin也可以)
.title{
position: relative;
top: -3em;
}
是不是有點奇怪了?其實就是往上位移了2行的距離,這樣在文本A 只有一行的時候,文本B 就剛好“出界”了;在文本A 有多行的時候,由于高度只有2行的高度,文本B 剛好“覆蓋”在上面,原理示意如下
這時,如果把父級的高度限制在一行,并且把文本B做單行截斷
.wrap{
line-height: 1.5;
height: 1.5em;
}
.title{
position: relative;
top: -3em;
white-space: nowrap;
text-overflow: ellipsis;
overflow: hidden;
}
這樣,在多行的時候,視野內看到的就是文本B了,效果如下
最后,把父級超出隱藏,還有文本B背景設置成父級相同的顏色就可以了~
到這里為止,就實現了文章開頭所示的效果,完整代碼可以查看 codepen auto title(記得鼠標放上去o~)
為了更方便直觀的演示,這里做了一個類似的列表如下
在線例子可訪問 codepen auto title list(記得鼠標放上去o~)
三、其他實用案例
下面再介紹兩個更加實用的提示效果
- 中間省略效果
細心的小伙伴可能已經發現,文章開頭的文本超出時,省略號是在中間的。
這種設計有什么好處呢?比如有時候很多文件的名稱是相同的,只有后綴名不同,或者很多會有個版本號,舉個栗子:
當寬度較小時,末尾出現了省略號,這就很尷尬了,由于前面都是一樣的,一眼看上去完全分不清文件名哪個跟哪個()
如果省略號在中間就很好區分了。那么,如何實現這一效果呢?
借助上面的布局,下面所有分析只需要對 文本B 進行處理就行了。關于中間省略效果,目前還沒有專門的 CSS 樣式可以實現,不過可以模擬它,接著往下看
首先,復制一份文本,這里使用 ::before 偽類通過 content 生成
.title::before{
content: attr(title);
}
很明顯,這個時候兩段文本是連接在一起的
然后,給 :before 設置右浮動,寬度設置成 50%
.title::before{
content: attr(title);
width: 50%;
float: right;
}
接著,給 :before 設置超出截斷
.title::before{
/**/
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
最后,把 :before 換成前面省略號的效果,可以用 direction 實現,關于 direction,平時可能沒怎么接觸,其實就是改變排版方向的,默認是從左到右,省略號在右側,如果改成從右到左,那么省略號也會在左邊,所以
.title::before{
/**/
direction: rtl; /*從右到左*/
}
現在看看完成效果吧
有一點小問題,中間的省略號左邊的空隙有時候有點大,如下
這個是因為這個地方剛好換行了,所有空出了一小截。這里可以用文本兩端對齊簡單優化一下
.title{
/**/
text-align: justify;
}
這樣就能保證最右端的文字是靠右的(當然文本的間隙會略微增加一點~),效果如下
在線例子可訪問 codepen auto middle ellipsis(記得鼠標放上去o~)
- 超出滾動效果
有時候,title 提示可能有點弱,不夠明顯,產品需要文本超出的時候,鼠標放上去可以自動滾動起來,類似這樣的效果
如何實現的呢?其實借助上面的布局,這里實現就非常容易了,只需要對 文本B 做滾動動畫即可,關于 CSS3實現無縫滾動,這里介紹一下實現:
要做到首尾無縫滾動,首先需要復制一份相同的文本,這里使用 ::after 偽元素通過 content 生成
.title::after{
content: attr(data-title);/*復制一份文本,下圖綠色的部分*/
}
現在需要在一行顯示,不換行
.title{
/**/
white-space: nowrap;
}
可以看到,雖然不換行了,但是寬度還是父級的寬度,并沒有跟隨文字內容,這時,可以設置 display: inline-block
.title{
/**/
display: inline-block;
white-space: nowrap;
}
關于寬度跟隨文字內容,其實還可以用 width: max-content 實現,兼容性略差
.title{
/*
display: inline-block;
white-space: nowrap;
*/
width: max-content;
}
接著,設置 animation 動畫即可,只需要當 transform 位移到 自身一半50% 時 迅速歸位,就能達到無縫銜接的效果,如下
.title:hover{
/**/
animation: move 10s .3s linear infinite;
}
@keyframes move {
to {
transform: translateX(-50%); /*位移到 50% 時 迅速歸位*/
}
}
這里首尾的間隙是用 padding 實現的
.title::after{
content: attr(data-title);
padding: 0 5em;/*無縫滾動的首位間隙*/
}
在線例子可訪問 codepen auto scroll list(記得鼠標放上去o~)
唯一的缺陷是動畫時間是固定的,如果文本很長,可能出現滾動過快的問題
四、總結和說明
本文介紹了一種全新 CSS 自動判斷多行文本的思路,并且帶來3個人性化的小交互。總的來說,其實也沒用到太多的技巧(主要還是想象力),結構還不算復雜,相信一步步看下來不會有很大的難度。
重點依舊是上面的布局部分,布局出來了,下面很多擴展效果也就迎刃而解了。由于只用到了 CSS2 相關特性(max-height、文本截斷等),兼容性也是棒棒的,實測可以兼容到 IE7+(全兼容,放心使用),后面的超出滾動效果兼容到 IE10+, 現在總結一下實現重點:
- 轉換思路,節點復制是一個好辦法
- 通過 max-height 可以判斷單行和多行
- 靈活運用 CSS 障眼法 層級覆蓋和超出隱藏
- direction:rtl 可以實現前置省略號的效果
- 中間省略號可以用兩段文本拼接的方式模擬
- 寬度跟隨文本自適應可以用 inline-block 實現
- 無縫滾動效果可以用位移 -50% 來實現
好了,這樣一個成本低廉,又非常人性化的小功能,趕緊用起來吧。如果大家覺得不錯的話,歡迎點贊、收藏、轉發???~
References
[1] [codepen auto title] https://codepen.io/xboxyan/pen/WNppXxx
[2] [codepen auto title list] https://codepen.io/xboxyan/pen/eYvveBe
[3] [codepen auto middle ellipsis] https://codepen.io/xboxyan/pen/VwpPNbm
[3] [codepen auto scroll list] https://codepen.io/xboxyan/pen/ZEeerBb