本文翻譯自CSS Ellipsis: How to Manage Multi-Line Ellipsis in Pure CSS,文中某些部分有些許改動,並添加譯者的一些感想,請各位讀者諒解。javascript
合理的截斷多行文本是件不容易的事情,咱們一般採用幾種方法解決:css
overflow: hidden
直接隱藏多餘的文本html
text-overflow: ellipsis
只適用於單行文本的處理java
各類比較脆弱的javascript實現。之因此說這種實現比較脆弱是因爲須要文本長度的變化時刻獲得迴流(relayout)後的佈局信息,如寬度web
原文寫做時間是2012.9.18號,比較有意義的一天。不過做者忽略了WebKit提供的一個擴展屬性
-webkit-line-clamp
,它並非CSS規範中的屬性。利用該屬性實現多行文本的省略號顯示須要配合其餘三個屬性:display: -webkit-box
、-webkit-box-orient
、text-overflow: ellipsis;
。其中,-webkit-line-clamp
設置塊元素包含的文本行數;display: -webkit-box
設置塊元素的佈局爲伸縮佈局;-webkit-box-orient
設置伸縮項的佈局方向;text-overflow: ellipsis;
則表示超出盒子的部分使用省略號表示。瀏覽器
不過本文將要介紹的方法是採用CSS規範中的屬性,並結合特殊的實現技巧完成的。這意味着在實現CSS2.1規範的瀏覽器中都是能夠兼容的,不將僅僅是純粹的移動端領域,在傳統的PC瀏覽器(大家懂得我指的是哪些瀏覽器)中還是可行的。好吧,讓咱們一塊兒見識下。佈局
咱們把實現的細節劃分爲7個步驟,在這個實現過程當中最簡單的就是截斷文本,而最難的部分則是讓一個元素處在其父包含塊溢出時的右下方,而且當父元素未溢出時該元素消失不可見。爲了去難避易,咱們先從比較簡單的地方開始--當父包含框比較小時,將子元素佈局到父包含框的右下角。優化
其實這個實現徹底利用了元素浮動的基本規則。在這裏不詳細講解CSS2.1規範中的幾種情形,不明白的讀者自行查閱。這段代碼實現很簡單,就是三個子元素和包含塊的高度及浮動設置:url
<div class="wrap"> <div class="prop">1.prop<br>float:left</div> <div class="main">2.main<br>float:right<br>Fairly short text</div> <div class="end">3.end<br>float:right</div> </div> .wrap { width: 400px; height: 200px; margin: 20px 20px 50px; border: 5px solid #AAA; line-height: 25px; } .prop { float: left; width: 100px; height: 200px; background: #FAF; } .main { float: right; width: 300px; background: #AFF; } .end { float: right; width: 100px; background: #FFA; }
咱們經過建立一個子元素來替代將要顯示的省略號,當文本溢出的情形下該元素顯示在正確的位置上。在接下來的實現中,咱們建立了一個realend元素,並利用上一節end元素浮動後的位置來實現realend元素的定位。spa
<div class="wrap"> <div class="prop"> 1.prop<br> float:right</div> <div class="main"> 2.main<br> float:left<br> Fairly short text</div> <div class="end"> <div class="realend"> 4.realend<br> position:absolute</div> 3.end<br>float:right </div> </div> .end { float: right; position: relative; width: 100px; background: #FFA; } .realend { position: absolute; width: 100%; top: -50px; left: 300px; background: #FAA; font-size: 13px; }
這一步中,咱們主要關心的是realend元素的定位,基於浮動後的end元素設置偏移量,當end元素浮動到第一節第二章圖的位置時(即在prop元素的下方),此時realend元素正好處在end元素的上方50px,右側300px-100px=200px處,而該位置正是父包含框wrap元素的右下角,此時正是咱們期待的結果:
若父元素並無溢出,那麼realend元素會出如今其右側
這種狀況解決很簡單,請看下文之第七節,此處僅做實例說明。
在第二節中,咱們針對end元素設置了相對定位,對realend元素設置絕對定位。可是咱們能夠採用更爲簡單的代碼來實現,即只使用相對定位。熟悉定位模型的同窗應該知道,相對定位的元素仍然佔據文本流,同時仍可針對元素設置偏移。這樣,就能夠去掉end元素,僅針對realend元素設置相對定位。
<div class="wrap"> <div class="prop">1.prop<br>float:right</div> <div class="main">2.main<br>float:left<br>Fairly short text</div> <div class="realend"> 3.realend<br>position:relative</div> </div> .realend { float: right; position: relative; width: 100px; top: -50px; left: 300px; background: #FAA; font-size: 14px; }
其餘的屬性並不改變,效果同樣。
目前,最左側的prop元素的做用在於讓realend元素在文本溢出時處在其正下方,在前幾節的示例代碼中爲了直觀的演示,設置prop元素的寬度爲100px,那麼如今爲了更好的模擬實際的效果,咱們縮小逐漸縮小prop元素的寬度。
<div class="wrap"> <div class="prop">1.prop<br>float:right</div> <div class="main">2.main<br>float:left<br>Fairly short text</div> <div class="realend"> 3.realend<br>position:relative</div> </div> .prop { float: left; width: 5px; height: 200px; background: #F0F; } .main { float: right; width: 300px; margin-left: -5px; background: #AFF; } .realend { float: right; position: relative; top: -50px; left: 300px; width: 100px; margin-left: -100px; padding-right: 5px; background: #FAA; font-size: 14px; }
針對prop元素,縮小寬度爲5px,其他屬性不變;
針對main元素,設置margin-left:5px,讓main元素左移5px,這樣main元素在寬度上就徹底佔滿了父元素;
對於realend元素,top、left和width的值不變。而設置margin-left: -100px
、padding-right: 5px
則是爲了讓realend元素的盒模型的最終寬度計算爲5px。
BoxWidth = ChildMarginLeft + ChildBorderLeftWidth + ChildPaddingLeft + ChildWidth + ChildPaddingLeft + ChildBorderRightWidth + ChildMarginRightWidth;
具體可參考我以前的文章負margin的原理以及應用一文。
因爲CSS規範規定padding的值不能夠爲負數,所以只有設置margind-left爲負值,且等於其寬度。這樣作的最終目的就是保證realend元素處在prop元素的下方,保證在文本溢出的狀況下定位準確性:
目前,realend元素的相關屬性仍採用px度量,爲了更好的擴展性,能夠改用%替代。
同時,prop元素和realend元素能夠採用僞元素來實現,減小額外標籤的使用。
<div class="ellipsis"> <div>2.main<br>float:left<br>Fairly short text </div> </div> /*至關於以前的prop元素*/ .ellipsis:before { content: ""; float: left; width: 5px; height: 200px; background: #F0F; } /*至關於以前的main元素*/ .ellipsis > *:first-child { float: right; width: 100%; margin-left: -5px; background: #AFF; } /*至關於以前的realend元素*/ .ellipsis:after { content: "realend"; float: right; position: relative; top: -25px; left: 100%; width: 100px; margin-left: -100px; padding-right: 5px; background: #FAA; font-size: 14px; }
效果圖和上節同樣。
以前的實現中在文本未溢出的狀況下,realend元素會出如今父元素的右側,正如。解決此問題很簡單,急須要設置:
.ellipsis{ overflow:hidden; }
便可解決問題。
如今咱們離結完就差一步了,即去掉各元素的背景色,而且用「...」替換文本。最後爲了優化體驗,採用漸變來隱藏「...」覆蓋的文本,並設置了一些兼容性的屬性。
到了此處,相信如今關心的只是CSS的代碼了:
.ellipsis { overflow: hidden; height: 200px; line-height: 25px; margin: 20px; border: 5px solid #AAA; } .ellipsis:before { content:""; float: left; width: 5px; height: 200px; } .ellipsis > *:first-child { float: right; width: 100%; margin-left: -5px; } .ellipsis:after { content: "\02026"; box-sizing: content-box; -webkit-box-sizing: content-box; -moz-box-sizing: content-box; float: right; position: relative; top: -25px; left: 100%; width: 3em; margin-left: -3em; padding-right: 5px; text-align: right; background-size: 100% 100%; /* 512x1 image, gradient for IE9. Transparent at 0% -> white at 50% -> white at 100%.*/ background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAgAAAAABCAMAAACfZeZEAAAABGdBTUEAALGPC/xhBQAAAwBQTFRF////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////AAAA////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////wDWRdwAAAP90Uk5TgsRjMZXhS30YrvDUP3Emow1YibnM9+ggOZxrBtpRRo94gxItwLOoX/vsHdA2yGgL8+TdKUK8VFufmHSGgAQWJNc9tk+rb5KMCA8aM0iwpWV6dwP9+fXuFerm3yMs0jDOysY8wr5FTldeoWKabgEJ8RATG+IeIdsn2NUqLjQ3OgBDumC3SbRMsVKsValZplydZpZpbJOQco2KdYeEe36BDAL8/vgHBfr2CvTyDu8R7esU6RcZ5ecc4+Af3iLcJSjZ1ivT0S/PMs3LNck4x8U7wz7Bv0G9RLtHuEq1TbJQr1OtVqqnWqRdoqBhnmSbZ5mXapRtcJGOc4t2eYiFfH9AS7qYlgAAARlJREFUKM9jqK9fEGS7VNrDI2+F/nyB1Z4Fa5UKN4TbbeLY7FW0Tatkp3jp7mj7vXzl+4yrDsYoVx+JYz7mXXNSp/a0RN25JMcLPP8umzRcTZW77tNyk63tdprzXdmO+2ZdD9MFe56Y9z3LUG96mcX02n/CW71JH6Qmf8px/cw77ZvVzB+BCj8D5vxhn/vXZh6D4uzf1rN+Cc347j79q/zUL25TPrJMfG/5LvuNZP8rixeZz/mf+vU+Vut+5NL5gPOeb/sd1dZbTs03hBuvmV5JuaRyMfk849nEM7qnEk6IHI8/qn049hB35QGHiv0yZXuMdkXtYC3ebrglcqvYxoj1muvC1nDlrzJYGbpcdHHIMo2FwYv+j3QAAOBSfkZYITwUAAAAAElFTkSuQmCC); 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); }
從上文的實現細節來看,咱們利用的技巧徹底是CSS規範中的浮動+定位+盒模型寬度計算,惟一存在兼容性問題的在於無關痛癢的漸變實現,所以能夠在大多數瀏覽器下進行嘗試。