问题提出
之前做项目需求的时候呢。会经常碰到文本内容超出的问题。通常UI设计师会叫我们超出的话显示省略号。由于之前做这样的需求一直没有整理文本内容超出省略的方案。那么这篇博客就好好整理一下吧。
我们知道CSS3定义了一个文本省略方案text-overflow
MDN上是这么说的:
text-overflow 是一个css 属性,确定如何向用户发出未显示的溢出内容信号。它可以被剪切,显示一个省略号(…)或者显示一个自定义的字符串
1 | text-overflow: ellipsis || clip || <string> |
clip:
在内容区域的极限处截断文本。因此在字符串的中间可能在中间发生截断
ellipsis:
用一个省略号(…)表示被截断的文本。这个省略号被添加在内容区域中。因此会减少显示文本。 如果是空间太少,那么省略号也会被截断。
<string>:
用自定义字符串来表示被截断的文本。字符串内容将被添加在内容区域中,所以会减少显示出的文本。如果空间太小到连省略号都容纳不下,那么这个字符串也会被截断。
但是有一点要非常注意:
这个属性只对那些块级元素溢出的内容有效。但是必须与块级元素内联(inline)方向一致(举一个反例:内容在盒子的下方溢出。此时就不会生效)
这句话简单的理解就是:text-overflow 只管行文本溢出的省略。
于是文本省略分成了单行文本省略和多行文本省略。
单行文本省略
由以上我们知道text-overflow 是可以解决单行文本省略的。但是毕竟是css3出的属性, 我们先看看它的兼容性:
可以看出它的兼容性是非常好的。所以可以放心愉快的使用吧
当然了,不是只使用text-overflow:ellipsis 就可以实现文本省略的。
上头我们我们也说过:
这个属性只对那些块级元素溢出的内容有效。但是必须与块级元素内联(inline)方向一致(举一个反例:内容在盒子的下方溢出。此时就不会生效)
文本可能在以下情况下溢出:当其因为某种原因而无法换行(例如:设置了”white-space:nowrap”),或者一个单词因为太长而不能合理地被安置(fit)。
因此为了让text-overflow 能够生效。我们必须要在元素上添加几个属性和满足一些规则:
- 块级元素
- overflow:计算值非visible
- 元素的宽度:超出时, 有一个确切的计算值
- white-space:nowrap || pre
解释一下这几个规则:
- overflow确实是非visible, 但是计算值并不是设定值, 因为css有个叫inhert的关键字
- 元素宽度: 不是元素的width。max-width,以及flex 布局都是可以的。
- white-space:pre也是可以的, 因为这个属性的设置主要就是为了不折行。
举个比较普遍的例子:
html:
1 | <div class="name"> |
css:
1 | .name { |
结果:
flex布局实现
html:
1 | <div class="name"> |
css:
1 | .name { |
结果:
其他的规则:
其余的其他设置我就不一一举例验证了。如果验证的时候有问题可以给我留言。
多行文本省略
使用 webkit-line-clamp
多行文本的省略,也有实现方法,但是只是针对webkit系浏览器**-webkit-line-clamp**
MDN上是这么说的:
–webkit-line-clamp: CSS属性 可以把块容器中的内容限定为指定的行数
–webkit-line-clamp 的语法:
1 | -webkit-line-clamp: none || integer |
- none:表示值显示的内容不会被限制
- integer: 这个值表示内容显示多少行之后会被限制,必须大于0
这个属性的规则:
- -webkit-line-clamp 只有在 display 设置为**-webkit-box** 或者**-webkit-inline-box** 并且设置**-webkit-box-orient** 为vertical时才有效果
- 在大部分情况下,也需要设置overflow属性为
hidden
, 否则,里面的内容不会被裁减,并且在内容显示为指定行数后还会显示省略号(ellipsis ).
来看个例子:
html:
1 | <div class="line"> |
css:
1 | .line { |
结果:
我们最后来看看 -webkit-line-clamp的兼容性:
兼容性和上头的 text-overflow 比起来,很惨。都是清一色的Webkit。 而且-wbkit-line-clamp 连 line-clamp 都不是。为什么是-webkit-line-clamp
呢?因为
- W3C没规范
- Webkit系自己YY的:所以带-webkit-
而且由以上的规则我们知道-webkit-line-clamp 依赖与 box 布局,而且是最老的Flex布局方案,已经由最新版的代替flex替代。 如果这个这个属性要进W3C规范,就得改改了。 换一句话来说,现在的写法很有可能在未来不再使用。估计结局是这两种:
- W3C收录规范:规则要改,因为box迟早会被废弃
- W3C自己定义一个新的属性:整个废弃掉
结论:如果是不是别误选择,还是不建议使用
大多数网上的方案(css)
本着一种能使用css 实现的, 就不用js实现的想法。
在使用其他css 方式之前, 我们来看一下无论单行还是多行实现超出省略的原理:
不管是多行截断还是多行截断,实际上,浏览器并没有把超长的文字删除,而是在渲染的时候在块尾渲染一个”…”覆盖在上面。规则里面的overflow的计算值为非visible, 所以在视觉上是看不到的。
所以我们自己实现的方式的原理也是这样的(拿个… 盖到上面去)
…的方案很简单,可以使用一个特定的元素, 也可以使用::after伪元素。我们可以看一个例子。
html:
1 | <div class="line"> |
css:
1 | .line { |
结果:
现在, 一切看都挺不错的。顺便网上一搜, 都是这样的实现方案。
但是,这个方案存在一个很严重的问题:默认的认为内容一定会溢出
网上写这个方案的时候有些也会还有一些提示:计算一下内容会不会溢出。
额,这提示…还不入不提示。 如果需要 js 计算, 那好不如一开始就使用js的方式实现了呢。为啥还整出 css + js 的方案呢?
一个完美的方案
如果我们想实现 仅仅当内容溢出时, 显示…省略 这样的方案, 我们该如何做呢?
我们回想一下我们上头的方案,我们是拿”…“ 盖住了右下角的内容来实现的省略。其实, 同样的道理,我们可以 拿个东西盖住…
原理还是那个原理,只是换了谁盖谁,所以我们的实现方案可以是:当且仅当内容溢出时,不盖住…
但是, 我们如何使用css 实现这样的效果呢? 我们怎么知道什么时候内容溢出呢?
我们抽象理解一下这个方案:
假设我们的内容是用一个数组存储的,我们的内容框只能承载20个字,也就是说,我们的数组length一旦大于20,index >= 20的元素就不能再显示了。
现在,我们的数组是空的,我们给它丢个字(假设为:略)进去,使用栈方法,从头往里一直丢字(unshift(‘X’),X为某个字),那第一次丢进去的“略”字,就会被一直往后推,直到它被推到20的位置,“略”字就“不再显示”了。
原理:
对...
的覆盖,我们也用“推”的方法,想象一下,我们找个东西
,把它盖到...
上,这就是第一个字“略”,然后,我们一直在这个东西
前面添加我们的文本内容,当我们把这个东西
推到框外时,就意味着我们的内容溢出了,...
需要显示。而在此之前,由于东西
一直处在index < 20
,所以,它就一直存在,一直盖住...
,这就是:内容未溢出,不显示...
原理讲完了, 我们来简单实现一下这个方案,这个原理实现的方案很多, 看自己怎么写。看个例子:
html:
1 | <div class="line"> |
css:
1 | .line { |
结果: 当内容没有超出的时候, 省略号(…)被盖住。当内容超出时。省略号(…)不被盖住
这是我认为的比较完美的纯css 方案了