文本换行(white-space 、word-break、overflow-wrap)与 文本省略(text-overflow)

1,457 阅读8分钟

最近面试的时候被问到通常文本省略和文本换行怎么去处理,菜鸟的我下意识就说文本省略的话设置text-overflow 属性值为 ellipsis ,文本换行的话通过设置 word-break 属性来处理。话音刚落,面试官沉默了一下,显然对我的回答不太满意。然后又问我什么情况下text-overflow什么情况下会失效呢?我说,文本换行了就失效了。接着面试官又问,那么在换行的情况下,又如何去处理呢?emmmm......

对此,也是来深入了解下与文本省略和文本换行相关的这些属性。

由于 text-overflow 在某些情况下会失效,需要配合某些属性一起使用,所以先来看看与文本换行的一些属性。

一、文本换行(white-space、word-break、overflow)

1.1 white-space

white-space 顾名思义,就是空白,严格来说该属性是用来设置如何处理元素中的空白的。

该属性有如下取值:

属性值描述
normal(默认值) 连续的空白符会被合并,换行符会被当作空白符来处理
nowrap连续的空白符会被合并。但文本内的换行无效
pre连续的空白符会被保留。在遇到换行符或者<br>元素时才会换行。(preserve)
pre-wrap连续的空白符会被保留。在遇到换行符或者<br>元素,或者需要为了填充时才会换行。
pre-line连续的空白符会被合并。在遇到换行符或者<br>元素,或者需要为了填充时会换行。

下面就基于以下HTML结构来详细了解下每个属性值的作用

<style>
    .text {
        margin: 50px
    }
    .text {
        width: 100px;
        height: 200px;
        border: 1px solid black;
    }
</style>

<div class="text">
    这是一段测试文本      空白后的文本
    第二行文本<br/>换行标签后文本
    Third Line LongTextaaaaaaaa
</div>

(1)normal

noraml 是默认值,表示连续的空白字符会被合并,换行符也会被当作空白符处理。

white-space: normal;

如图所示,“这是一段测试文本 空白后的文本” 之间的空白符被合并成了,而且每一行的换行符也是当作空白符来处理了。但是 <br/> 换行标签和通过&nbsp定义的空格不会受到影响。

image.png

(2)nowrap

nowrap,顾名思义,就是不换行。即:连续的空白字符会被合并,但是文本内的换行无效。

white-space: nowrap

如下图所示,与normal的主要区别在于,当文本到达盒子边界时,文本不会自动换行。但是遇到<br/>标签仍然会换行。

image.png

(3)pre

pre其实是单词 preserve(保留) 的缩写,这样一来就比较容易理解了。即:连续的空白符会被保留。在遇到换行符或者<br>元素时才会换行

white-space: pre

如图所示,所有的空白字符都保留了,而且文本遇到换行符时会换行,不会当作空白字符处理。当文本到达盒子边界时并不会自动换行。

image.png

(4)pre-wrap

pre-wrap可以理解为 pre + wrap,与 pre 不同的在于当文本到达盒子边界时会自动换行。

white-space: pre-wrap

image.png

(5)pre-line

pre-linepre-wrap 不同的在于,pre-line 会合并空白字符。(需要注意的是,pre-line 也不会将换行符当作空白符处理)

white-space: pre-line

image.png

其实还有个break-space属性,但是需要比较高版本的浏览器才能兼容,所以暂且引用MDN上的一段介绍:

break-spaces 与 pre-wrap的行为相同,除了:

  • 任何保留的空白序列总是占用空间,包括在行尾。
  • 每个保留的空格字符后都存在换行机会,包括空格字符之间。
  • 这样保留的空间占用空间而不会挂起,从而影响盒子的固有尺寸(最小内容大小和最大内容大小)。

white-space 不同值的行为总结如下:

换行符空格和制表符文字换行行尾空格
normal合并合并换行删除
nowrap合并合并不换行删除
pre保留保留不换行保留
pre-wrap保留保留换行挂起
pre-line保留合并换行删除
break-spaces保留保留换行换行

有关什么时候文本会自动换行,可参考该文档:www.w3.org/TR/CSS2/vis…

1.2 word-break

1.1 中的 white-space 主要是对空白字符的处理,遇到换行符时如何处理,以及文本到达边界时是否自动换行等。 那么接下来的 word-break 属性就是用于指定怎样在单词内断行

word-break 属性的值如下所示:

属性值描述
normal(默认值)使用默认的断行规则
break-all对于 non-CJK (CJK 指中文/日文/韩文) 文本,可在任意字符间断行
keep-allCJK 文本不断行。Non-CJK 文本表现同 normal
break-word在空格处断行(已弃用)

那么基于下面代码来详细了解一下word-break

(1)normal

默认值,使用默认的断行规则。

image.png

(2)keep-all

CJK 文本不断行。Non-CJK 文本表现同 normal

word-break: keep-all

如下图所示,中文和日语文本都没有断行,但是遇到空格会断行。可以理解为保持所有单词不拆分,因此连续的 CJK 文本也会被当作一个单词,不会被拆分。或者也可以理解为,遇到空格才会换行

image.png

(3)break-all

break-all:不论什么语言,只要文本碰到边界就换行。对于英文,会从单词中间将单词断开。

word-break: break-all

image.png

(4)break-word

break-word:其实就是对于CJK 文本遇到边界就换行,而非CJK 文本,只有遇到单行放不下的单词时会分割。

word-break: break-word

image.png

1.3 overflow-wrap

overflow-wrap是用来说明当一个不能被分开的字符串太长而不能填充其包裹盒时,为防止其溢出,浏览器是否允许这样的单词中断换行。是由 word-wrap 属性转换而来。

word-wrap 属性原本属于微软的一个私有属性,在 CSS3 现在的文本规范草案中已经被重名为 overflow-wrap 。 word-wrap 现在被当作 overflow-wrap 的 “别名”。 稳定的谷歌 Chrome 和 Opera 浏览器版本支持这种新语法。

overflow-wrap 属性值如下所示:

属性值描述
normal行只能在正常的单词断点处中断(例如两个单词之间的空格)
break-word表示如果行内没有多余的地方容纳该单词到结尾,则那些正常的不能被分割的单词会被强制分割换行。

(1)normal

在正常单词断点处中断

overflow-wrap: normal

image.png

(2)break-word

当某个很长的单词到达边界时,会被强制分割。(该属性常会用到)

overflow-wrap: break-word

image.png

二、文本省略(text-overflow)

text-overflow 属性用于确定如何提示用户存在隐藏的溢出内容。其形式可以是裁剪、显示一个省略号(“”)或显示一个自定义字符串。

text-overflow 属性可能被赋予一个或者两个值。

  • 如果赋一个值,指的行末溢出行为(从左至右的文本右末端,从右至左的文本左末端)。
  • 如果赋两个值,第一个值指定行左端溢出行为,第二个值指定行右端溢出行为。

text-overflow 属性的值如下所示,

属性值描述
clip默认值,这个关键字会在内容区域的极限处截断文本,因此可能会在单词的中间发生截断
ellipsis这个关键字会用一个省略号('…')来表示被截断的文本。这个省略号被添加在内容区域中,因此会减少显示的文本。如果空间太小以至于连省略号都容纳不下,那么这个省略号也会被截断。
string用来表示被截断的文本(实验阶段)
  • clip

image.png

  • ellipsis

image.png

有关文本溢出处理,本文主要关注两点

(1)text-overflow 什么时候生效

text-overflow 只有在单行文本超过边界的时候设置才会生效,所以必须配合以下两个属性一起使用。

white-space: nowrap;
overflow-x: hidden;

(2)如果是多行文本,那么如果进行文本省略呢?

有关这个问题,也是参考一位大佬的想法。

既然text-overflow只能用于单行文本的情况,那么多行文本的时候当然就失效了。其实我们可以:

  • 首先获取内容区域的宽度
  • 然后计算内容区文本的总长度
  • 将文本总长度除以内容区域宽度,预估文本需要多少行
  • 然后自定义每一行放置哪些文本(即如何分割文本)
  • 自定义要显示的行数,然后在最后一行对省略符号(自定义)进行拼接

这样也就实现多行文本的省略。

因为是大佬的想法,这里就不贴代码了,提供一个思路供大家参考。或许还有更好的方法,也欢迎大家交流。

好了,本文到这就结束啦!