前言
這是個老掉牙的需求啦,不過仍然有很多人在網上找解決方案,特別是搜尋結果排名靠前的那些,都是些只會介紹相容性不好的使用-webkit-line-clamp
的方案。
如果你看到這篇文章,可能代表你正是從那麼多千篇一律的文章中跳轉過來的,想找更好地方案的。那恭喜你,沒有更好的,只有更合不合適的,當然,前提是我的文章流量夠多,能被頂上去你才有機會看到。
這裡介紹三種多行文字截斷的方法,當然第一種就是你看到想吐的
-webkit-line-clamp
方案,不想看就直接跳到第二種方法開始看啦。
使用-webkit-line-clamp
對多行文字的容器應用如下樣式
div {
display: -webkit-box;
-webkit-box-orient: vertical;
overflow: hidden;
-webkit-line-clamp: 2;
}
複製程式碼
除了-webkit-line-clamp
其他屬性固定不變,主要是將物件作為彈性伸縮盒子模型顯示,並設定伸縮盒物件的子元素的排列方式。
而-webkit-line-clamp
是用來控制多少行進行省略
優點:
- 瀏覽器原生支援的省略行為,樣式看起來很舒服
- 簡單方便使用
缺點:
- 看屬性的字首就知道,這是
webkit
核心的瀏覽器支援的,相容性不是廣泛。
使用場景
如果你只針對webkit核心瀏覽器或者移動端(移動端瀏覽器多數是webkit核心),那麼使用該方案是最好的了。
利用絕對定位
這個方案其實很好理解的,首先我們對於一個裝內容的容器右邊預留一個空間用來放省略號,用padding-right: 1em;
來預留空間,為啥是1em呢,一個省略號差不多就是1em啦,用em單位是為了響應字型大小。
用絕對定位把省略號定位在這個預留的空間右下角。
html
<div class="wrap">內容</div>
複製程式碼
css
.wrap3 {
position: relative;
padding-right: 1em;
/*max-height是line-height的幾倍,想最多顯示多少行就幾倍*/
max-height: 3.6em;
line-height: 1.2em;
text-align: justify;
overflow: hidden;
}
.wrap3:before {
position: absolute;
right: 0;
bottom: 0;
content: '...';
}
複製程式碼
效果(多內容時):
這樣的話,省略號永遠都會存在的。 所以要解決這個問題,我們用一個跟背景顏色一樣的方塊遮住省略號,那麼關鍵點就是,怎麼知道何時要遮住,何時不遮住呢?
思路: 用於擋住省略號的方塊也是絕對定位,靠右定為,right: 0
,但是bottom
值就不要設定了,如果不設定的話,該方塊會跟著文字內容的實際高度移動,而不是max-height
的高度。這樣的話,當不需要省略時(即不超過max-height
)時,就剛好是bottom: 0
的情況,就會擋住省略號。當要進行省略時(即超過max-height
)就會擋不住省略號了,它自己也會被overflow: hidden
給隱藏掉了。
所以最終方案是:
html
<div class="wrap">內容</div>
複製程式碼
css
.wrap {
position: relative;
/*line-height和height要相互配合,顯示多少行就省略,就是line-height多少倍數*/
line-height: 1.2em;
max-height: 3.6em;
/*此屬性看需求來判斷是否設定,因為設定了padding-right,多騰出了點位置,該值一般為padding-right的值的負值*/
/*margin-left: -1em;*/
/*此值寫死成1em就好,因為省略號大概就是佔用1em的空間*/
padding-right: 1em;
text-align: justify;
overflow: hidden;
}
.wrap:before {
position: absolute;
right: 0;
bottom: 0;
content: '...';
}
.wrap:after {
position: absolute;
right: 0;
/*寬高寫死1em就好,因為省略號大概就是佔用1em的空間,用來遮擋住省略號,也基本上跟wrap的padding-right一致*/
width: 1em;
/*與wrap的行高實際值保持一致*/
height: 1.2em;
content: '';
/*要跟所在背景顏色一致才能遮擋住省略號後覺得沒異樣*/
background-color: #fff;
}
複製程式碼
效果:
優點
- 相容性好,各大瀏覽器支援
- 自適應高度,不用寫死高度,設定超過多少行才需要進行省略顯示
- 自適應寬度
- 自適應字型大小,字型大小不會影響到原本的需求,即要求多少行省略就多少行才省略
缺點
- 文字右邊會故意留空一些位置給省略號放置
- 需要考慮所在的背景顏色,因為after偽類要用背景顏色來遮擋住省略號
利用float佈局
這個方案對於基礎知識不紮實的童鞋們,可能不太好理解,如果僅是想找個解決方案不想知道原理的話,可以直接去 小結 裡看
在說該方案之前,要先理解這麼一個現象:
有這麼一段html
<div class="wrap">
<div class="left">左浮動</div>
<div class="right1">右浮動1右浮動1右浮動1右浮動1右浮動1右浮動1右浮動1右浮動1右浮動1右浮動1右浮動1右浮動1右浮動1右浮動1右浮動1右浮動1</div>
<div class="right2">右浮動2</div>
</div>
複製程式碼
應用這麼一段樣式
.wrap {
height: 100px;
}
.left {
float: left;
width: 60px;
height: 100%;
background: pink;
}
.right1 {
float: right;
/*佔滿wrap除left剩餘寬度*/
width: calc(100% - 60px);
background: #95d9f8;
}
.right2 {
float: right;
background: yellow;
}
複製程式碼
正常情況下會顯示成這樣,這也是大家一般所能想象的預期情況:
出現這個正常現象的條件是:
.right1
的高度不超過.left
的高度(即內容少).right2
的寬度少於.right1
的寬度
好了,這個情況大家理解了吧。那麼接下來,我們對.right1
的內容增多至超出左浮動的高度,會發生接下來的一幕
要問我為什麼會這樣?額...看來你對float的基礎知識不紮實呀,建議夯實一下基礎知識,其實我也解釋不了,我只知道這是float的一個正常表現。
出現這個現象的條件是:
.right1
的高度超過.left
的高度(即內容多).right2
的寬度少於或等於.left
的寬度
知識轉化成需求實現
在理解了上述兩個情景後,我們應該怎麼利用這些知識來匹配對應的需求呢?
假設右浮動1的文字內容就是我們要進行多行省略的內容,右浮動2的內容就是省略號(...)。這樣當內容少時,省略號就是上述的第一個情況,內容多的時候就是第二個情況。
這種動態變化,是不是像“文字少時不省略,文字多時進行省略”這種需求變化呢。在這個基礎上,我們要解決的是在第一種情況右浮動2隱藏掉,第二種情況下右浮動2出現在.wrap
的右下角,超出高度的內容隱藏掉。
要解決上述問題,只要使用position: relative;
進行相對定位即可。.wrap
父容器應用overflow: hidden;
。 第一種情況下,定位到父容器外部,就隱藏掉了。而第二種情況,就定位到父容器右下角。
好了,現在該解決方案的焦點,就放在如何準確定位的問題上了(下一小節)。在處理定位問題前,先把目前掌握的情況轉化為實際的需求程式碼:
<!--把左浮動和右浮動2採用偽類元素替換掉實際標籤-->
<div class="wrap">
<div class="text">右浮動1</div>
</div>
複製程式碼
.wrap {
height: 100px;
/*line-height用來控制最多顯示多少行文字*/
line-height: 20px;
overflow: hidden;
}
.wrap:before {
float: left;
/*要大於或等於after元素寬度*/
width: 1.5em;
height: 100%;
content: '';
}
.text {
float: right;
/*用負值的marginLeft來避免由before產生的空白空間*/
/*因為實際需求上你的父容器裡不可能左邊是一片空白吧*/
margin-left: -1.5em;
/*既然採用了負值marginLeft,那麼文字容器寬度就可以100%佔滿父容器寬度了*/
width: 100%;
}
.wrap:after {
float: right;
/*一般三個點就差不多1em寬,用em作單位能自適應字型大小*/
width: 1em;
content: '...';
}
複製程式碼
如果你這時候好奇,為什麼.text
都設定了width: 100%;
了,內容多時:after
還是會卡在:before
底下呢?是因為即使.text
設定了margin-left: -1.5em;
,但是實際上並不會影響到原本的文件流情況,原本該是怎樣的就是怎樣,設定了負值的margin,影響的只是.text
自身的呈現樣式。
如何定位
解決定位問題是基於上小節的程式碼基礎上。目前暴露的問題有:
- 內容少即不需要做省略時,省略號顯示出來了
- 內容多即需要省略時,省略號隱藏了
先解決第二個問題
思路:要把這個:after
向右移動到.wrap
右邊,向上移動到最後一行的位置。
用position: relative;
來控制的話,top
值好取,取.wrap
的line-height
實際值一樣,取負值就好了。關鍵是left值,怎麼取才能剛好在右下角呈現出來。
如果你能明確知道.text
的寬度的話(如100px),其實設定left: 100px;
即可,但是這樣的話只能針對固定寬的情況,不能自適應寬度。要想實現自適應,left的值取百分比就行了,那麼到底是百分之多少呢?這是糾結的。索性就取100%吧,會發現會移出到父容器外。
那要剛好出現在右下角的話,省略號的初始位置就必須要在.wrap
的左側,緊挨著.wrap
,才能left: 100%
後出現在右下角。
現在問題就變成如何讓:after
剛好出現在.wrap
的左側了。
以下程式碼對於基礎不紮實的人,可能有些難理解了(新增部分在註釋處):
.wrap:after {
float: right;
/*因為下面設定了margin,所以這裡的寬度值大小沒有要求*/
width: 1em;
content: '...';
/*這兩個屬性是設定緊挨著.wrap左側*/
/*此值要跟自身寬度一樣,取負值*/
margin-left: 1em;
/*此值要跟before寬度一樣*/
padding-right: 1.5em;
/*這是定位省略號的位置*/
position: relative;
left: 100%;
/*與父元素wrap的行高實際值一樣,取負值*/
top: -20px;
}
複製程式碼
關於設定margin和padding值那裡,如果你能理解就最好了,不能理解的話,我儘量解釋一下,其實這也真不好說。
首先是應用margin-left: 1em;
的時候,由於:after
的寬度比:before
的要小,所以按照原本的float佈局的話,在一行裡
按照上述原理,設定了margin-left: 1em;
後,:after
就變回到父容器的第一行上了,緊挨著父容器左側。但是我們不能讓它回到第一行上呀,所以設定padding-right: 1.5em;
讓它實際佔的空間變大到第一行容不下它,就變回到原本的卡在:before
下的位置,只是padding值讓它移動到左側了
好了我解釋完了,能不能看懂,只能看你的造化了哈哈。
值得留意的是,上面程式碼裡關於width的註釋寫著“因為下面設定了margin,所以這裡的寬度值大小沒有要求”,之前都要求小於等於:before
寬度,但是現在由於採用margin-left負值抵消了本身的寬度,所以這個要求轉化對padding-right
了,這時是等於
小結
到目前位置,所有問題都解決了。針對上述所有討論的問題,總結為以下程式碼(具體優化有註釋說明):
css樣式
.wrap {
/*需要定高*/
height: 100px;
/*用來設定顯示多少行才省略,值一般為wrap的height值/行數求得,但是這個行數會受到字型大小的限制*/
/*字型太大了,設定顯示很多行也會很醜,都擠一塊了,所以這個實際值,要看具體需求和實踐*/
line-height: 25px;
/*加上此屬性顯示效果更佳,就算部分瀏覽器不支援也影響不大*/
text-align: justify;
overflow: hidden;
}
.wrap:before {
float: left;
/*這個值可以隨意設定,不論單位還是什麼*/
width: 1em;
height: 100%;
content: '';
}
.wrap:after {
float: right;
/*大小隨意,設定em單位最好,可隨字型大小變化而自適應*/
/*如果要採用以下漸變效果,那麼這個值要大於before裡的width值效果會比較好點*/
/*值越大,漸變的效果越明顯影響的範圍越大。*/
width: 2.5em;
/*與父元素wrap的行高實際px值一樣*/
height: 25px;
/*此值要跟自身寬度一樣,取負值*/
margin-left: -2.5em;
/*此值要跟before寬度一樣*/
padding-right: 1em;
content: '...';
text-align: right;
/*這裡開始利用在float佈局的基礎上進行定位移動了*/
position: relative;
/*與父元素wrap的行高實際值一樣,取負值*/
top: -25px;
left: 100%;
/*設定漸變效果是為了省略號和內容銜接得自然點,沒那麼突兀,要注意要跟文字所在的背景的顏色搭配(把white替換成背景色)*/
background: #fff;
background: -webkit-gradient(linear, left top, right top, from(rgba(255, 255, 255, 0)), to(white), color-stop(50%, white));
background: -moz-linear-gradient(to right, rgba(255, 255, 255, 0), white 50%, white);
background: -o-linear-gradient(to right, rgba(255, 255, 255, 0), white 50%, white);
background: -ms-linear-gradient(to right, rgba(255, 255, 255, 0), white 50%, white);
background: linear-gradient(to right, rgba(255, 255, 255, 0), white 50%, white);
}
.wrap .text {
float: right;
/*該值要等於wrap:before的width值*/
margin-left: -1em;
width: 100%;
}
複製程式碼
html檔案:
<div class="wrap">
<span class="text">
示例2: 散發設解決看手機啦開發交
</span>
</div>
複製程式碼
效果:
優點
- 相容性好,滿足不是webkit核心的瀏覽器都能支援
- 自適應寬度
缺點
- 固定高度,不能自適應高度,因此顯示多少行還要受字型大小限制
- 需要為文字包裹一個標籤用以設定樣式
- 從讀樣式程式碼上來看,理解起來不是很好理解
- 如果省略號所在元素不用漸變色背景,偶爾會截斷得突兀,如果要用漸變色背景,要注意與文字所在的背景下的顏色搭配
總結
其實沒有說哪個方案更好,只有合不合適你的方案,叫你去削個水果皮,拿把水果刀就好了,沒必要用個大刀。所以,三個方案,總有一款符合你的需求的。