原創(chuàng)文章,轉(zhuǎn)載請(qǐng)注明出處。
背景
在項(xiàng)目需求開發(fā)時(shí),由于文本內(nèi)容長度的不確定性,經(jīng)常會(huì)碰到文本內(nèi)容超出的問題,通常這種情況,UI/UE都會(huì)要求我們將超出部分用省略號(hào)(...)來顯示,這種做法基本上已經(jīng)是一個(gè)業(yè)界共識(shí)了。然而,這么一個(gè)理所當(dāng)然的效果,在前端卻一直是一個(gè)難題。
希望
對(duì)于文本省略,由于CSS3的出現(xiàn),出現(xiàn)了單行文本省略和多行文本省略的劃分了(看完Can I Use,你會(huì)覺得這句話不合理,可,那又如何,哈哈(?ω?)hiahiahia)。之所以這么說,那是因?yàn)镃SS3定義了一個(gè)文本省略方案:
text-overflow: ellipsis | clip;
這在前端界可謂是相當(dāng)膩害的進(jìn)步,前端大拿、二拿、小拿們紛紛舉起鍵盤YY:前端的巨輪勢不可擋!
永遠(yuǎn)在那綠油油的田野上
不得不說,text-overflow的出現(xiàn) ,確實(shí)讓前端為之動(dòng)容,多么美好,哪里還需要什么JS算字?jǐn)?shù)啊。然而,真正用上text-overflow才發(fā)現(xiàn),理想很美好,現(xiàn)實(shí)很骨感,這哥們只管單行文本溢出的省略,對(duì)于多行文本,卻視而不見。
希望,依舊在那綠油油的田野上……
于是,文本省略從沒有變成了兩種:單行文本省略和多行文本省略。
單行文本省略
有,總比沒有好
這是一條永恒的道理,好歹,解決單行文本省略時(shí)候,我們可以開開心心用CSS解決,而不用再去搞有的沒的JS了。
用之前先看兼容
這是一條CSS規(guī)則。查Can I Use,這哥們的兼容性簡直震憾人心?。?br>

牛不牛,服不服,連讓你們?cè)嵅〉腎E都兼容到不可思議的地步了。(看到這里,我就想問,這哥們?cè)趺吹紺SS3才被定義哈)
當(dāng)然,并不是一條text-overflow: ellipsis;就可以實(shí)現(xiàn)文本省略。
無規(guī)矩,不成方圓
同樣,text-overflow的使用,需要滿足一些規(guī)矩:
- 塊級(jí)元素
- overflow: 計(jì)算值
非visible;- 元素寬度:超出時(shí),有一個(gè)確切的計(jì)算值
- white-space: nowrap | pre;
估計(jì)你們會(huì)發(fā)現(xiàn),上述的規(guī)矩和你們認(rèn)識(shí)的,或者在網(wǎng)上找到的教程不太一樣。嗯嗯,的確如此,搜索各類教程基本給的說法是這樣的:
- 塊級(jí)元素
- overflow: hidden; // 也有說非visible
- width: 具體值,非auto
- white-space: nowrap;
其實(shí),基本差不多,解釋一下不一樣的地方:
- overflow確實(shí)是
非visible,但是,是計(jì)算值,并不是設(shè)定值。因?yàn)镃SS里有個(gè)叫inherit的關(guān)鍵字。 - 元素寬度,而不是width,比如,max-width,以及厲害的flex布局也是可以的。
- white-space: pre; 也是可以的,這個(gè)屬性的設(shè)定主要是為了
不折行,pre也是可以達(dá)到目的。
每個(gè)規(guī)則我就不一一給例子驗(yàn)證了,如果有問題,歡迎評(píng)論留言哈。這里就簡單

P.S. 圖片來源于網(wǎng)絡(luò),但是沒找到源頭,若你們知道,麻煩告訴我,萬分感謝!若是作者看到,覺得不可使用,告知于我,必及時(shí)刪除之!width規(guī)則里,我們用flex布局:
<div style="display: flex;">
<div id="ellipsis-item" style="flex: 1;
white-space: nowrap;
overflow: hidden;
text-overflow:ellipsis;
">這是一串很長很長很長很長很長很長很長很長很長很長很長很長很長很長很長很長很長很長很長很長的文字</div>
<div style="flex: 1;">這是一串很長很長很長很長很長很長很長很長很長很長很長很長很長很長很長很長很長很長很長很長的文字</div>
</div>
把這坨下代碼放到你的頁面里,如果看不到...,縮小一下窗口,你會(huì)看到類似這樣的情況:

很顯然,代碼里,我們并沒有為
#ellipsis-item元素聲明width或是max-width屬性,但是,省略依然見效。原因就是,設(shè)定flex屬性后,元素就會(huì)被分配寬度計(jì)算值,從而使省略生效。在這個(gè)例子,寬度值是50%父元素寬度。
單行文本省略雖然不是本文的重點(diǎn),但是也簡單回顧一下,并完善些(可能不是完美)text-overflow的使用規(guī)則。
多行文本省略
也許有人會(huì)說,多行文本也有實(shí)現(xiàn)方法啊。確實(shí),在Webkit系瀏覽器里還是有的:
line-clamp
OK,再回顧一下。
Webkit系解決方案
和text-overflow一樣,我們先看一下兼容性:

兼容性和
text-overflow比起來,簡單是慘不能睹,真是清一色Webkit,而且,還是-webkit-line-clamp,連正經(jīng)的line-clamp都不是。為什么是-webkit-line-clamp呢?因?yàn)?p>
- W3C沒規(guī)范
- Webkit系自己YY的:所以帶-webkit-
- 規(guī)則上,這哥們要轉(zhuǎn)正,以后也得改哈
那就說下規(guī)則吧:
- display: -webkit-box | -webkit-inline-box;
- -webkit-box-orient: vertical | block-axis
- overflow: 計(jì)算值
非visible- -webkit-line-clamp: N; // 行數(shù)
可以看出來,-webkit-line-clamp依賴于box布局,而這家伙是最老的Flex布局方案,已經(jīng)由新版的flex系替代,所以說,這哥們即使進(jìn)W3C規(guī)范,估計(jì)也得改改了。
換句說,現(xiàn)在的寫法,很可能未來不能再使用,結(jié)局估計(jì)是這兩種:
- W3C收錄規(guī)范:規(guī)則要改,因?yàn)閎ox遲早會(huì)被廢棄
- W3C自己定義一個(gè)新的屬性:整個(gè)廢棄
所以,如果不是別無選擇,還是不太建議使用。
好殘酷,需求還要做,怎么辦。。。JS搞起啊,算字?jǐn)?shù)啊,加...
哈哈……
假裝很完美的方案
哇靠,講了那么多,總算回到標(biāo)題了。。扯了這么多,感覺成了標(biāo)題黨,會(huì)不會(huì)被打哈。。
那些用JS算寬度算字?jǐn)?shù)的方案我就不說了哈,你要是喜歡就自行到網(wǎng)上搜索唄。由于本人一貫的原則是:
能用CSS的,就不要用JS
所以,接下來這個(gè)方案,也必然是純CSS方案了。另外,給你們點(diǎn)繼續(xù)看下去的勇氣:
- 純CSS
- 高兼容性
- 適用于N行:不區(qū)分單行還是多行
首先,看個(gè)效果圖:

是不是看起來超厲害,是不是以為是用的
-webkit-line-clamp。。。然而,并不是哦。
其次,來理一下原理。
不管是單行截?cái)噙€是多行截?cái)?,事?shí)上,瀏覽器并沒有把超長的文字刪除,而是渲染時(shí)候在塊尾渲染個(gè)
...覆蓋在上面,由于規(guī)則里overflow: 計(jì)算值非visible,所以,視覺上是看不到的。
要驗(yàn)證我的說法是正確的,很簡單,把你們經(jīng)常用overflow: hidden;的寫法改成overflow: auto; 或overflow: scroll;即可。
所以,我們的原理也是這樣的,
拿個(gè)
...蓋到上面去
簡單搞個(gè)圖看下:

從上圖可以看到,實(shí)際上,我們要做的就是把粉色那個(gè)...,放在框的右下角,以隱藏右下角的最后那個(gè)字/內(nèi)容,當(dāng)我們把粉色改成白色,就會(huì)得到我們希望的...省略效果了:

說到這里,...的方案很簡單,可以使用一個(gè)特定的元素,也可以用::after偽元素。最后的代碼類似這樣的:
<div style="
margin: 50px;
width: 200px;
height: 3em;
line-height: 1.5;
overflow: hidden;
position:relative;outline:1px solid #ff9900
">這是一串很長的文字,現(xiàn)在開始哦。第二行文字在這里開始了
<i style="
position: absolute;
bottom: 0;
right: 0;
width: 1.5em;
padding-left: 2px;
background-color: white;
">...</i>
</div>
到目前為止,一切似乎很順利,網(wǎng)上隨便一搜,都差不多是這個(gè)樣子的?;蛟S,你們有人已經(jīng)在YY:你丫是在逗我嗎,這誰不知道哈。
誠然,如果我說的方案就到此結(jié)束,還真是在逗你們了,但是,請(qǐng)認(rèn)真繼續(xù)看哈。
這個(gè)方案有一個(gè)很嚴(yán)重的問題,那就是:
理所當(dāng)然地認(rèn)為內(nèi)容一定會(huì)溢出
是的,網(wǎng)上有些認(rèn)真的人在寫這個(gè)方案時(shí)候,還是會(huì)來個(gè)溫馨提醒的,有的也會(huì)告訴你計(jì)算一下內(nèi)容會(huì)不會(huì)溢出,如果是這樣,干嘛不一開始就直接計(jì)算得了,還整了一個(gè)CSS+JS計(jì)算的方案哈。
當(dāng)然,如果你可以百分百確定你的內(nèi)容會(huì)溢出,到目前為止的方案已經(jīng)足夠。相反,你應(yīng)該繼續(xù)看下去?;氐轿覄偛诺慕貓D里:

截圖里可以看到,我們最終的方案是要保證:
當(dāng)且僅當(dāng)內(nèi)容溢出時(shí),顯示...省略
究竟如何實(shí)現(xiàn)這個(gè)功能呢?回想一下我們這個(gè)...的方案原理,我們是拿...蓋住右下角的內(nèi)容來實(shí)現(xiàn)省略,其實(shí),同樣的道理,我們可以
拿個(gè)東西蓋住
...
是的,原理還是那個(gè)原理,只是換了誰蓋誰。所以,前面那句話,我們就可以換成:
當(dāng)且僅當(dāng)內(nèi)容溢出時(shí),不蓋住...
如何達(dá)到這個(gè)效果呢?要解釋這個(gè)問題,我們來具象一下overflow: hidden;是什么樣的一個(gè)效果。
假設(shè)我們的內(nèi)容是用一個(gè)數(shù)組存儲(chǔ)的,我們的內(nèi)容框只能承載20個(gè)字,也就是說,我們的數(shù)組length一旦大于20,index >= 20的元素就不能再顯示了。
現(xiàn)在,我們的數(shù)組是空的,我們給它丟個(gè)字(假設(shè)為:略)進(jìn)去,使用棧方法,從頭往里一直丟字(unshift('X'),X為某個(gè)字),那第一次丟進(jìn)去的“略”字,就會(huì)被一直往后推,直到它被推到20的位置,“略”字就“不再顯示”了。
同樣,對(duì)...的覆蓋,我們也用“推”的方法,想象一下,我們找個(gè)東西,把它蓋到...上,這就是第一個(gè)字“略”,然后,我們一直在這個(gè)東西前面添加我們的文本內(nèi)容,當(dāng)我們把這個(gè)東西推到框外時(shí),就意味著我們的內(nèi)容溢出了,...需要顯示。而在此之前,由于東西一直處在index < 20,所以,它就一直存在,一直蓋住...,這就是:內(nèi)容未溢出,不顯示...。
至此,原理簡單地抽象了一下。接下來,就是實(shí)現(xiàn)了,實(shí)現(xiàn)有很多方式,這里給出其中一種,具體怎么實(shí)現(xiàn),看個(gè)人喜好吧,畢竟
思想是統(tǒng)一的,實(shí)現(xiàn)都是看人的
給出以下某個(gè)實(shí)現(xiàn):
<style type="text/css">
.ellipsis {
margin: 20px;
}
.ellipsis {
position: relative;
width: 200px;
max-height: 3em;
line-height: 1.5;
overflow: hidden;
outline: 1px solid #ff9900;
}
.ellipsis::before {
content: '...';
position: absolute;
z-index: 1;
bottom: 0;
right: 0;
width: 1.5em;
padding-left: 3px;
box-sizing: border-box;
background-color: white;
}
.ellipsis::after {
content: '';
display: inline-block;
position: absolute;
z-index: 2;
width: 100%;
height: 100%;
background-color: white;
}
</style>
<div class="ellipsis">這是一串很長的文字</div>
<div class="ellipsis">這是一串很長的文字,現(xiàn)在開始哦。第二行文字在這</div>
<div class="ellipsis">這是一串很長的文字,現(xiàn)在開始哦。第二行文字在這里開始了,從“里”字開始,就應(yīng)該被...省略了。</div>
效果圖這樣的:

原理已經(jīng)講了,我就不再劃實(shí)現(xiàn)的要點(diǎn)了,多動(dòng)動(dòng)腦,不會(huì)有害處的。
只是比較完美
雖然,最后的實(shí)現(xiàn)效果圖上看,好像很完美的樣子,但是,這個(gè)方案,同樣有比較麻煩的地方,簡單舉例一下
- 中英文:純英文或純中文,比較簡單,但是,如果右下角的字不能確定是中文還是英文時(shí)候,
...的size和position的設(shè)定基本不會(huì)有一個(gè)完美值,有興趣的可以自行測試- 多選文本省略時(shí),內(nèi)容框的高度,要和N行高度保持一致,這是沒有辦法像瀏覽器處理那樣,可以處理行上的省略的(
overflow: hidden;只會(huì)截?cái)啵?/li>
其他的,我就不再舉例了。對(duì)于1,可以考慮用漸變混合一下,弱化問題,對(duì)于2,就乖乖設(shè)定高度吧。
總之,這是一個(gè)還算比較完美的方案,但是,還是有其缺陷。如果有更好的方案,再做補(bǔ)充吧,也歡迎評(píng)論提供。
總結(jié)
本文總結(jié)了文本省略的方案,既有對(duì)瀏覽器支持方案的一些新見解,也分享了自己的解決方案,來劃一下重點(diǎn):
text-overflow使用規(guī)矩:
- 塊級(jí)元素
- overflow: 計(jì)算值非visible;
- 元素寬度:超出時(shí),有一個(gè)確切的計(jì)算值
- white-space: nowrap | pre;
Webkit系列的多行文本省略:
- display: -webkit-box | -webkit-inline-box;
- -webkit-box-orient: vertical | block-axis
- overflow: 計(jì)算值
非visible- -webkit-line-clamp: N; // 行數(shù)
本人的方案:
- 在框右下角放個(gè)
...,蓋住右下角的內(nèi)容- 在內(nèi)容尾,跟隨一個(gè)mask,蓋住上述的
...,內(nèi)容超出時(shí),mask被推出,顯示...
P.S. 原創(chuàng)文章,轉(zhuǎn)載請(qǐng)注明出處。