多段落多行文本溢出省略号的实现

有时候我们需要实现多行文本溢出显示省略号的效果
例如:
目标效果

这个效果可以通过webkit的私有属性实现,以上限三行为例:

1
2
3
4
5
6
.multi-line {
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-line-clamp: 3;
overflow: hidden;
}

对于单个段落这个样式就够用了,但是当有多个段落时情况就不一样了

例如当后端以换行符的形式返回多段落文本时:

后端返回

实际上是不会有这样的效果的,因为换行符等空白符会被合并成一个空白符,实际上看起来只有一个空格。

通常换行的办法有两个:

  1. 分成两个block,如p标签
  2. 使用</br>换行
    然而方案1会让每一段的第三行末尾都有省略号(...),而方案2会使-webkit-line-clamp这一私有属性失效,那该如何是好呢?

回想一下,其实我们是有办法让换行符生效的(还记得我们在页面显示代码块的情景吗)。没错,就是white-space: pre;

但是让整段文本应用white-space: pre;显然不行(会整个乱套的),所以应该只让那个换行符应用white-space: pre;,那解决方案就出来了:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
.container {
transition: height .3s ease-in-out;
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-line-clamp: 3;
overflow: hidden;
}
.paragraph::after {
//其中`\A`是CSS里的换行符
content: '\A';
white-space: pre;
}
.paragraph:last-child::after {
white-space: normal;
}

这样就完成目标的效果啦~

One more thing

想给展开-收起加上一个平滑的过渡,那就要给height设置transition属性。但是应用了-webkit-line-clamp的元素的高度是自动计算得出的,即使设置transition: all .3s也不会有过渡效果。

为了使过渡效果生效,我们需要明确知道它具体从多少px变到了多少px。那我们只需要在一开始设height:auto;-webkit-line-clamp: initial;,用js计算出实际高度并存起来,如果超出3行,就设定到3行的高度和-webkit-line-clamp: 3;,这时切换样式就会有过渡效果了。

(实际上这也是高性能动画队列FILP的原理)