当前位置: 首页 > 科技观察

如何使用CSS实现多行文本的省略号显示

时间:2023-03-14 12:48:34 科技观察

本文翻译自CSSEllipsis:HowtoManageMulti-LineEllipsisinPureCSS,文章部分内容略有改动,部分思路已添加译者,请读者谅解。合理截断多行文本并不容易。我们通常使用几种方法来解决:overflow:hidden直接隐藏冗余文本text-overflow:ellipsis只适合单行文本处理各种脆弱的javascript实现。这个实现之所以脆弱,是因为文本长度发生变化时需要获取回流(relayout)后的布局信息,比如宽度。英文原文写于2012.9。但是,作者忽略了WebKit提供的一个扩展属性——webkit-line-clamp,它不是CSS规范中的属性。使用该属性实现多行文本的省略号显示需要配合其他三个属性:display:-webkit-box,-webkit-box-orient,text-overflow:ellipsis;。其中,-webkit-line-clamp设置块元素包含的文本行数;display:-webkit-box设置块元素的布局为灵活布局;-webkit-box-orient设置灵活项的布局方向;文本溢出:省略号;表示超出方框的部分用省略号表示。而本文要介绍的方法是利用CSS规范中的属性,结合特殊的实现技术完成的。这意味着所有实现CSS2.1规范的浏览器都是兼容的,不仅在纯移动领域,在传统的PC浏览器(你知道我指的是哪些浏览器)中也是如此。的。好吧,让我们一起看看。CSS实现多行文字溢出的省略号表示我们将实现细节分为7个步骤。这个实现过程中最简单的部分是截断文本,最难的部分是当元素的父包含块位于的右下角时让元素溢出,当父元素没有溢出时元素消失不可见。为了避难,我们先从一个比较简单的地方开始——当父包含框比较小时,子元素布局在父包含框的右下角。1stIntroduction事实上,这个实现充分利用了元素浮动的基本规则。CSS2.1规范中的几种情况我这里就不详细解释了,不懂的读者可以自行查看。这段代码的实现很简单,就是三个子元素和包含块的高度和浮动设置:1.prop
float:left

2.main
float:right
Fairlyshorttext
3.end
float:right
.wrap{width:400px;height:200px;margin:20px20px50px;border:5pxsolid#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元素的定位。1.prop
float:right2.main
float:left
Fairlyshorttext4.realend
position:absolute3.end
float:right.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元素浮动到Section2第2章图中的位置时(即prop元素下方),此时realend元素正好在end元素上方50px,300px-100px=200px在右边,而这个位置就是父包含框的wrap元素的右下角,这正是我们期望的结果:如果父元素没有溢出,那么realend元素就会出现在右边它。这种情况的解决方法很简单,请看下面第七节,这里只是举例。3rd优化定位模型在第二部分中,我们设置结束元素的相对定位和真正结束元素的绝对定位。但是我们可以用更简单的代码来实现,即只使用相对定位。熟悉定位模型的同学应该知道,相对定位的元素仍然占据着文本流,仍然可以为元素设置偏移量。这样就可以去掉end元素,只对realend元素设置相对定位。1.prop
float:right2.main
float:left
Fairlyshorttext3.realend
position:relative.realend{float:right;position:relative;width:100px;top:-50px;left:300px;background:#FAA;font-size:14px;}其他属性不变,效果一样。4th缩窄prop元素目前最左边的prop元素的作用是当文字溢出时让realend元素在其正下方。在前面几节的示例代码中,为了直观演示,prop元素的宽度设置为100px。所以现在为了更好的模拟实际效果,我们逐渐缩小prop元素的宽度。1.prop
float:right2.main
float:left
Fairlyshorttext3.realend
position:relative.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,其余属性不变;对于主元素,设置margin-left:5px,让主元素向左移动5px,使主元素在宽度上完全占据父元素;对于realend元素,top、left、width的值保持不变。而设置margin-left:-100px,padding-right:5px就是让realend元素的盒模型最终的宽度计算为5px。BoxWidth=ChildMarginLeft+ChildBorderLeftWidth+ChildPaddingLeft+ChildWidth+ChildPaddingLeft+ChildBorderRightWidth+ChildMarginRightWidth;具体可以参考我之前的文章负保证金的原理及应用。由于CSS规范规定padding的值不能为负数,所以只需将margin-left设置为负数且等于其宽度即可。这样做的最终目的是保证realend元素在prop元素下方,保证文字溢出情况下的定位精度:5th继续优化:流式布局+伪元素目前realend元素的相关属性还在测在px中,为了更好的扩展性,可以使用%代替。同时,prop元素和realend元素可以使用伪元素实现,减少额外标签的使用。
2.main
float:left
Fairlyshorttext
/*等价于前一个prop元素*/.ellipsis:before{content:"";float:left;width:5px;height:200px;background:#F0F;}/*相当于前面的主元素*/.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;}效果图同上一节。6th在前面的实现中,如果文本不溢出,realend元素会出现在父元素的右侧,如中。解决这个问题很简单,急需设置:.ellipsis{overflow:hidden;}来解决问题。7th大功告成现在我们离完成又近了一步,移除每个元素的背景颜色并将文本替换为“...”。***为了优化体验,使用渐变色隐藏被“...”覆盖的文字,并设置了一些兼容性属性。到了这里,相信现在关心的只是CSS的代码了:.ellipsis{overflow:hidden;height:200px;line-height:25px;margin:20px;border:5pxsolid#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%;/*512x1image,gradientforIE9.Transparentat0%->whiteat50%->whiteat100%。*/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,lefttop,righttop,from(rgba(255,255,255,0)),to(white),color-stop(50%,white));背景:-moz-linear-gradient(toright,rgba(255,255,255,0),white50%,white);背景:-o-linear-gradient(toright,rgba(255,255,255,0),white50%,white);背景:-ms-linear-gradient(toright,rgba(255,255,255,0),white50%,white);背景:线性渐变(toright,rgba(255,255,255,0),white50%,white);}兼容性总结从上面的实现细节来看,我们使用的技术完全是CSS规范中的浮动+定位+盒模型宽度计算,唯一有兼容性问题的是trivial渐变实现,所以在大多数浏览器下都可以尝试