33

_前端-溢出文本显示省略号

 5 years ago
source link: http://www.hongweipeng.com/index.php/archives/1756/?amp%3Butm_medium=referral
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

技术预研

以下测试仅测试:chrome 73/ff 66/edge 18 不保证所有主流浏览器兼容

单行

省略号处于尾部

简单使用 text-overflow:ellipsis 即可

当文本溢出包含元素时,显示省略符号来代表被修剪的文本

支持绝大部分浏览器(IE6+/xxxx

为了满足需求,还现需要进行其他css的设置,比如

white-space: nowrap;
overflow: hidden;
width: 100%;

由于是隐藏溢出,所以双击复制文本的时候,拿到的是全部的文本(不带省略号)

省略号处于首部

在使用上述 省略号处于尾部 的前提下,

利用 direction: rtl 即可实现。

考虑到父元素宽度足够大的时候文本会靠右显示,还得在父元素上设置 text-align: left;

<!DOCTYPE HTML>
<html>
<style type="text/css">
div {
  width:200px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  direction: rtl;
  text-align: left;
}
</style>
</head>
<body>
  <div>我和五个优秀员工,分别是xxxx</div>
</body>
</html>

后记:发现应用 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 则子元素为内联元素时,内联元素的排序规则还是从左往右显示

<!DOCTYPE HTML>
<html>
<style type="text/css">
div {
  text-align: left;
  width:250px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  direction: rtl;
}
.t1 {
  direction: ltr;
  unicode-bidi: embed;
}
</style>
</head>
<body>
  <div><span class="t1">12-</span>这是一段测试文本<span class="t1">!@#$</span></div>
</body>
</html>

根据该思路我们就得到了方案3↓

解决方案3(推荐):不分割,直接用再包装一个内联元素span,

<!DOCTYPE HTML>
<html>
<style type="text/css">
div {
  text-align: left;
  width:150px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  direction: rtl;
}
span {
 direction: ltr;
 unicode-bidi: embed;
}
</style>
</head>
<body>
  <div><span>12-这是一段测试文本!@</span></div>
</body>
</html>

省略号位于两边

一般使用的场景是,我们搜索到某个关键字,然后要居住展示该关键字,左右两边超过边界的字符都显示省略号

思路1

切分为两个字符串,前面字符串包含主要内容,后面字符串利用 省略号处于尾部 来显示 ...

前面的字符串还是和 省略号处于首部 的做法一样,定宽块里面包一个行内元素

然后再取一个兄弟元素 span 包住剩余字符串;

最后用一个div包住两者,该div宽度为前串div宽度+16,同时应用 省略号处于尾部 的样式

注意:为了自适应,前串的宽度定义为 max-width: calc(100% - 14px);

当父div足够大时,前面的字串会先展示,然后开始展示后面的字串

demo:

<!DOCTYPE HTML>
<html>
<style type="text/css">
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 {
}

</style>
</head>
<body>
  <div class="div">
    <span class="s1"><span>12-这是一段测试文本一段测试文本!@</span></span
    ><span class="s2">看的到我吗?</span>
  </div>
</body>
</html>

显示效果为:

12-这是一段测试文本一段测试文本!@ 看的到我吗?

注意:行内元素之间会带一个空格;代码里写成一行就不会

其他一些技巧: https://css-tricks.com/fighting-the-space-between-inline-block-elements/

注意:ff复制的话需要ctrl+a全选才行

由于前面设置了 overflow: hidden; (不应用的话是产生截断效果

可以看到后面的inline-block块会垂直偏下

基线问题的原因:

https://stackoverflow.com/questions/28887531/two-divs-same-line-why-overflow-hidden-causes-vertical-offset

https://www.w3.org/TR/CSS21/visudet.html#propdef-vertical-align

第一个字串设置 vertical-align: text-bottom; 即可

最终代码

<!DOCTYPE HTML>
<html>
<style type="text/css">
.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 {
}

</style>
</head>
<body>
  <div class="dot3-between">
    <span class="s1"><span>12-这是一段测试文本一段测试文本!@</span></span
    ><span class="s2">看的到我吗?</span>
  </div>
</body>
</html>

前串: str.substr(0,str.indexOf(pat))

思路2:

切分为两个字符串,各占50%,分别显示省略号

与上个效果不同,当父元素变大的时候,左右两边的字符会一起不断展示

策略1:当父元素足够大的时候,文字始终居中

要点在于前串设置 width:50%;

<!DOCTYPE HTML>
<html>
<style type="text/css">
.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;
}

</style>
</head>
<body>
  <div class="div">
    <div class="s1"><span>12-这是一段测试文本!@1</span></div
    ><span class="s2">吱吱吱吱看的到我吗?</span>
  </div>
</body>
</html>

策略2:当父元素足够大的时候,文字始终居左

要点在于前串设置 max-width:50%;

<!DOCTYPE HTML>
<html>
<style type="text/css">
.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;
}

</style>
</head>
<body>
  <div class="div">
    <div class="s1"><span>12-这是一段测试文本!@1</span></div
    ><span class="s2">吱吱吱吱看的到我吗?</span>
  </div>
</body>
</html>

字符串切割:

简单: str.substr(0,str.length/2)

复制: 统计字符宽度,取中值

字符宽度统计函数

注意:ff复制的话需要ctrl+a全选才行,且最后复制出来中间会有换行

省略号位于中间(或字串的某个位置)

思路1

参考 省略号位于两边-策略2

依旧需要对字符串进行切分

<!DOCTYPE HTML>
<html>
<style type="text/css">
.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;
}

</style>
</head>
<body>
  <div class="div">
    <div class="s1">12-这是一段测试文本!@1</div
    ><span class="s2"><span>吱吱吱吱看的到我吗?</span></span>
  </div>
</body>
</html>

中间显示的省略号一开始为 ...... ,后面可能为 ... (如果某个消失而某个还存在的话),最后消失

注意:ff和edge两个省略号中间会存在空白

注意:ff复制的时候会有换行

如果想保持只有一个...的话

未完待续。。。


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK