image-20190517091416254

最近在开发文件管理器时,遇到文件名称省略显示的问题,文件名称后缀是很重要的信息,当名称过长显示不下时,最好的体验是省略中间,如:

纯CSS实现文本中间…适应宽度[原创].md

并且显示区域宽度是可以拖动调节的,希望名称能根据宽度动态调节省略的显示,使省略的位置保持在中间。

要实现这种效果,有两种思路:

JavaScript实现

一种是用JavaScript获取名称显示宽度,然后计算名称字符数(中文要算2个),从而得到单位字符宽度,然后得到要省略掉的字符数,最后拼接出符合宽度的名称;这里有2个问题,一是字符的宽度是不统一的,可能存在较大误差,使得拼接后的名称可能大于或小于显示区域;第二个问题是动态自适应不好实现,因为用的是element-ui的table组件,拖动列的时候不知道怎么触发名称处理。

CSS实现

第二种思路是采用CSS来实现,首先把文本分成前后两段,各占一半。

然后一般的想法是在前面文本用以下代码在的末尾加上 ”…“,然后把后面的文本拼在一起。

1
2
3
white-space:nowrap;		// 不换行;
overflow:hidden;
text-overflow:ellipsis; // 超出变省略号;

但是效果如下,后面跟前面会断开,因为前面的字符直接截掉后面超出的字符,就会有多余的不到一字的宽度多出来。

纯CSS实现文本中间… 适应宽度[原创].md

前面对齐实现

为了解决这个问题,如何让字符占满内容区域的宽度呢?刚开始想右对齐,但左边又对不齐了,那就两端对齐,这里需要换行才有效,还要加上高度值,把下面超出的隐藏掉::

1
2
3
4
white-space:normal;  //换行
height: 1.8em;
overflow: hidden; //隐藏下边的换行
text-align: justify; //两端对齐

后面对齐实现

前面的对齐了,但是”…”就显示不了,这时就可以把”…”放在后面字符的前面,需要用到 direction: rtl; ,它会将作用元素内部包含的内联元素的排布方向变为从右到左(本来是用于阿拉伯文等从右到左排版的实现)。

还需要配合unicode-bidi: plaintext; 使用,不然字符顺序会乱掉,这个属性可以控制字符的顺序,甚至可以完全反过来,原理可参考bidi 算法及 HTML 中的实现

最后,通过text-align: left;把字符贴齐左边。

1
2
3
4
5
6
white-space: nowrap;
overflow: hidden;
direction: rtl;
unicode-bidi: plaintext;
text-align: left;
text-overflow: ellipsis;

完整实现

最后还要注意前后两段字符要拼起来,并能自适应宽度,需要在有父级包裹,并采用flex布局,完整代码如下

1
2
3
4
<div class="name-wrap">
<span class="name-head">纯CSS实现文本中间省略显示并</span>
<span class="name-end">能动态自适应宽度[原创].md</span>
</div>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
.name-wrap {
background-color: lightgrey;
display: flex;
}
.name-head {
background-color: greenyellow;
//flex: 0 1 auto;
white-space: normal; //换行
height: 1.8em;
overflow: hidden; //隐藏下边的换行
text-align: justify; //两端对齐,后边不留白
}
.name-end {
background-color: lightgreen;
//flex: 0 1 auto;
white-space: nowrap; //不换行
direction: rtl; //内联元素顺序变为从右到左
unicode-bidi: plaintext; //
overflow: hidden; //
text-align: left;
text-overflow: ellipsis;
}

实现效果

完整显示

image-20190517091144063

省略显示

image-20190517091416254

正常显示

仔细看会注意到有些前面的字符间距可能比后面大,这就是两边对齐把原来后面多余的间距平分到每个字符上了,效果还是不错的。

image-20190517195007443