_前端-溢出文本显示省略号
技术预研
以下测试仅测试:chrome 73/ff 66/edge 18 不保证所有主流浏览器兼容
单行
省略号处于尾部
简单使用 text-overflow:ellipsis
即可
当文本溢出包含元素时,显示省略符号来代表被修剪的文本
支持绝大部分浏览器(IE6+/xxxx
为了满足需求,还现需要进行其他css的设置,比如
white-space: nowrap; overflow: hidden; width: 100%;
由于是隐藏溢出,所以双击复制文本的时候,拿到的是全部的文本(不带省略号)
省略号处于首部
在使用上述 省略号处于尾部
的前提下,
利用 direction: rtl
即可实现。
考虑到父元素宽度足够大的时候文本会靠右显示,还得在父元素上设置 text-align: left;
div { width:200px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; direction: rtl; text-align: left; }我和五个优秀员工,分别是xxxx
后记:发现应用 direction:rtl
后,处于尾部的特殊字符将以从右往左的顺序排列在字符串前面,字符串前面的字符以从左往右的顺序显示再右边;
或者单独的数字串也会
比如
12-这是一段测试文本!@#$
用于rtl后变成 $#@!这是一段测试文本-12
应用ellipsis后变成 ...测试文本-12
所以需要引入 unicode-bidi
,决定如何处理文档中的双书写方向文本
取值:
https://developer.mozilla.org/zh-CN/docs/Web/CSS/unicode-bidi
https://www.w3.org/TR/CSS2/visuren.html#propdef-unicode-bidi
normal:设置了 direction:rtl,则图片、按钮以及问号、加号之类的字符会从右往左显示,但是中文、英文字符还是从左往右显示 embed:作用在内联元素上,与normal的作用一样,但不受外部影响 bidi-override:所有的字符都按照统一的 direction 顺序排列 plaintext:不考虑父元素的双向状态,也不考虑 direction 属性的值。也就是会按我们的文本顺序显示
设置plaintext后,目前测试chrome是完美支持的。
但是!
ff 在设置该属性后,将不会再出现省略号
edge,ie 该属性只有前三种值,故首尾特殊字符位置不对
解决方案1:左右加入特殊空白符: ㅤ
, 然后进行相对定位及移动;
这样保证了前面不会的特殊字符不会移动,同时unicode-bidi 不做处理。
缺点就是需要进行相对定位的一些兼容处理,同时复制出来会带个特殊空白符
解决方案2:算法识别前后会造成偏移的字符串,进行切割
如 12-这是一段测试文本!@
切割变成 12-
这是一段测试文本
!@
然后前后的字符串用 span(内联元素) 包装起来,并设置 direction:ltr
以及 unicode-bidi: embed;
embed 以 direction方向为准,故该字串里面字符显示会以ltr的顺序,即 !@
不会变成 @!
那么首尾两个字符串为什么不会交换呢?
MDN 上对于 normal有句解释:对双向算法,此元素不提供额外的嵌入级别。对于内联元素,隐式的重新排序在元素的边界上起作用。
父级div为normal 则子元素为内联元素时,内联元素的排序规则还是从左往右显示
div { text-align: left; width:250px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; direction: rtl; } .t1 { direction: ltr; unicode-bidi: embed; }12-这是一段测试文本!@#$
根据该思路我们就得到了方案3↓
解决方案3(推荐):不分割,直接用再包装一个内联元素span,
div { text-align: left; width:150px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; direction: rtl; } span { direction: ltr; unicode-bidi: embed; }12-这是一段测试文本!@
省略号位于两边
一般使用的场景是,我们搜索到某个关键字,然后要居住展示该关键字,左右两边超过边界的字符都显示省略号
思路1
切分为两个字符串,前面字符串包含主要内容,后面字符串利用 省略号处于尾部
来显示 ...
前面的字符串还是和 省略号处于首部
的做法一样,定宽块里面包一个行内元素
然后再取一个兄弟元素 span 包住剩余字符串;
最后用一个div包住两者,该div宽度为前串div宽度+16,同时应用 省略号处于尾部
的样式
注意:为了自适应,前串的宽度定义为 max-width: calc(100% - 14px);
当父div足够大时,前面的字串会先展示,然后开始展示后面的字串
demo:
div { width: 200px; text-align: left; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } .s1 { display:inline-block; text-align: left; max-width: calc(100% - 14px); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; direction: rtl; } .s1 span { direction: ltr; unicode-bidi: embed; } .s2 { }12-这是一段测试文本一段测试文本!@看的到我吗?
显示效果为:
12-这是一段测试文本一段测试文本!@
看的到我吗?
注意:行内元素之间会带一个空格;代码里写成一行就不会
其他一些技巧: https://css-tricks.com/fighting-the-space-between-inline-block-elements/
注意:ff复制的话需要ctrl+a全选才行
由于前面设置了 overflow: hidden;
(不应用的话是产生截断效果
可以看到后面的inline-block块会垂直偏下
基线问题的原因:
https://www.w3.org/TR/CSS21/visudet.html#propdef-vertical-align
第一个字串设置 vertical-align: text-bottom;
即可
最终代码
.dot3-between { width: 200px; text-align: left; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } .dot3-between .s1 { display:inline-block; text-align: left; max-width: calc(100% - 14px); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; direction: rtl; vertical-align: text-bottom; } .dot3-between .s1 span { direction: ltr; unicode-bidi: embed; } .dot3-between .s2 { }12-这是一段测试文本一段测试文本!@看的到我吗?
前串: str.substr(0,str.indexOf(pat))
思路2:
切分为两个字符串,各占50%,分别显示省略号
与上个效果不同,当父元素变大的时候,左右两边的字符会一起不断展示
策略1:当父元素足够大的时候,文字始终居中
要点在于前串设置 width:50%;
.div { width: 200px; } .s1 { display:inline-block; width:50%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; direction: rtl; } .s1 span { direction: ltr; unicode-bidi: embed; } .s2 { width:50%; display:inline-block; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; text-align: left; }12-这是一段测试文本!@1吱吱吱吱看的到我吗?
策略2:当父元素足够大的时候,文字始终居左
要点在于前串设置 max-width:50%;
.div { width: 200px; } .s1 { display:inline-block; max-width:50%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; direction: rtl; } .s1 span { direction: ltr; unicode-bidi: embed; } .s2 { width:50%; display:inline-block; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; text-align: left; }12-这是一段测试文本!@1吱吱吱吱看的到我吗?
字符串切割:
简单: str.substr(0,str.length/2)
复制: 统计字符宽度,取中值
字符宽度统计函数
注意:ff复制的话需要ctrl+a全选才行,且最后复制出来中间会有换行
省略号位于中间(或字串的某个位置)
思路1
参考 省略号位于两边-策略2
依旧需要对字符串进行切分
.div { width: 200px; } .s1 { max-width:50%; display:inline-block; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; text-align: right; } .s2 { display:inline-block; max-width:50%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; direction: rtl; text-align: left; } .s2 span { direction: ltr; unicode-bidi: embed; }12-这是一段测试文本!@1吱吱吱吱看的到我吗?
中间显示的省略号一开始为 ......
,后面可能为 ...
(如果某个消失而某个还存在的话),最后消失
注意:ff和edge两个省略号中间会存在空白
注意:ff复制的时候会有换行
如果想保持只有一个…的话
未完待续。。。