在前端开发过程中【单行文本内容过长使用省略号展示】这是一个特别常见的功能,大家都知道要使用 text-overflow 这个 css 属性。
关于这个属性,我们可以先看一下官方文档怎么说。
text-overflow
CSS 属性用于确定如何提示用户存在隐藏的溢出内容。其形式可以是裁剪、显示一个省略号(“…
”)或显示一个自定义字符串。
但是实际应用的过程中,没有那么简单,尤其是在 flex 布局中,text-overflow 有的时候不生效。我总结了一些一些常用的场景,大家最好自己复制代码自己调试一下,看看区别,对我们提高开发效率有很大的作用。
不瞒你说,在整理这篇文章之前,在 flex 布局中超长文本省略号无效这个问题确实困扰了我一段时间。text-overflow 属性有的时候有效,有的时候无效,然后改 bug 的时候,给各种dom 乱增加一些属性就好使了,我也觉得莫名其妙的就好了,也不知道原理是什么,这篇文章可以从根本上理解一下,反正我是顿悟了,至少关于这个的 bug 可以分分钟改好了。
1. 文本省略号展示的三个必备属性
单行文本内容过长之用省略号展示需要用到的三个 CSS属性如下:
- white-space: nowrap; 设置不可折行
- overflow: hidden; 设置超出宽度隐藏
- text-overflow: ellipsis; 设置文本内容用省略号展示
注意,这三个属性是需要给文本内容的直接父元素设置的,如下:
<div style="white-space: nowrap; overflow: hidden; text-overflow: ellipsis">很长很长的文本,需要用省略号展示的文本</div>
2. 块元素/行内元素/行内块元素
块元素/行内元素/行内块元素【直接包含文本内容】的时候,直接给标签设置上面的三个属性就可以,不会有无效的情况;
2.1 代码
<div class="block-wrapper"><div class="label">类型一:块元素/行内元素/行内块元素【直接包含文本内容】</div><div class="type-label">【有效】不设置宽度 + 单个【块元素】标签</div><div style="background: red; white-space: nowrap; overflow: hidden; text-overflow: ellipsis">LongTextLongTextLongTextLongTextLongTextLongText</div><div class="type-label">【有效】不设置宽度 + 单个【行内元素】标签</div><span style="background: red; white-space: nowrap; overflow: hidden; text-overflow: ellipsis">LongTextLongTextLongTextLongTextLongTextLongText</span><div class="type-label">【有效】不设置宽度 + 单个【行内块元素】标签</div><div style="display: inline-block; background: red; white-space: nowrap; overflow: hidden; text-overflow: ellipsis">LongTextLongTextLongTextLongTextLongTextLongText</div>
</div>
2.2 实际效果
3. flex 布局的子项目
flex 布局的子项【包含文本内容】时,且在该子项目本身是 flex 布局的时候 text-overflow 无效。
3.1 代码
<div class="block-wrapper"><div class="label">类型二:flex 布局的子项目【包含文本内容】</div><div class="type-label">【有效】flex 容器【宽度固定】 + 块级元素子项</div><div style="background: red; display: flex; width: 200px"><!-- div 块元素 --><div style="white-space: nowrap; overflow: hidden; text-overflow: ellipsis">LongTextLongTextLongTextLongTextLongTextLongText</div></div><div class="type-label">【有效】flex 容器【宽度固定】+ 行级元素子项</div><div style="background: red; display: flex; width: 200px"><!-- span 行内元素 --><span style="white-space: nowrap; overflow: hidden; text-overflow: ellipsis">LongTextLongTextLongTextLongTextLongTextLongText</span></div><div class="type-label">【有效】flex 容器【宽度固定】+ 子项手动设为行内元素</div><div style="background: red; display: flex; width: 200px"><!-- 手动设为行内元素--><div style="display: inline; white-space: nowrap; overflow: hidden; text-overflow: ellipsis">LongTextLongTextLongTextLongTextLongTextLongText</div></div><div class="type-label">【有效】flex 容器【宽度固定】+ 子项手动设为行内块元素</div><div style="background: red; display: flex; width: 200px"><!-- div 作为flex项目,又设置为 inline-block 元素 --><div style="display: inline-block; white-space: nowrap; overflow: hidden; text-overflow: ellipsis">LongTextLongTextLongTextLongTextLongTextLongText</div></div><div class="type-label">【有效】flex 容器【宽度固定 百分比】+ 子项手动设为行内元素</div><div style="background: red; display: flex; width: 100%"><div style="display: inline; white-space: nowrap; overflow: hidden; text-overflow: ellipsis">LongTextLongTextLongTextLongTextLongTextLongText</div></div><div class="type-label">【有效】flex 容器【宽度固定 vw】+ 子项手动设为行内元素</div><div style="background: red; display: flex; width: 20vw"><div style="display: inline; white-space: nowrap; overflow: hidden; text-overflow: ellipsis">LongTextLongTextLongTextLongTextLongTextLongText</div></div><div class="type-label error">【无效】flex 容器【宽度固定 vw】+ 子项手动设为 flex 布局</div><div style="background: red; display: flex; width: 20vw"><div style="display: flex; white-space: nowrap; overflow: hidden; text-overflow: ellipsis">LongTextLongTextLongTextLongTextLongTextLongText</div></div>
</div>
3.2 实际效果
解决这个无效情况很简单,就是不要给文本内容的直接父元素设置成 flex 布局就行了。
4. 三层结构以上 flex 布局
三层结构以上的 flex 布局是我们在项目实践中最常遇到的场景,因为我们现在大面积的使用 flex 布局,dom 层层嵌套。三层结构以上 flex 布局情况分为两种,一种是 flex 容器宽度固定;一种是 flex 容器宽度不固定,使用 flex-grow 等自适应。
当 flex 容器的宽度自适应 text-overflow 属性可能会失效。
4.1 代码
<div class="block-wrapper"><div class="label">类型三:三层结构以上 flex 布局</div><div class="type-label error">【无效】第三层 flex 容器【宽度固定】+ 第二层宽度自适应 + 文本内容</div><!-- 第三层 --><div style="background: red; display: flex; width: 200px"><!-- 第二层宽度自适应,不做任何处理 --><div><!-- 文本内容 --><div style="white-space: nowrap; overflow: hidden; text-overflow: ellipsis">LongTextLongTextLongTextLongTextLongTextLongText</div></div></div><div class="type-label error">【无效】第三层 flex 容器【宽度固定】+ 第二层宽度自适应【flex-grow】 + 文本内容</div><!-- 第三层 --><div style="background: red; display: flex; width: 200px"><!-- 第二层宽度自适应 --><div style="display: flex; flex-grow: 1"><!-- 文本内容 --><div style="white-space: nowrap; overflow: hidden; text-overflow: ellipsis">LongTextLongTextLongTextLongTextLongTextLongText</div></div></div><div class="type-label">【有效】第三层 flex 容器【宽度固定】+ 第二层【overflow:hidden】 + 文本内容</div><!-- 第三层 --><div style="background: red; display: flex; width: 200px"><!-- 第二层宽度自适应,增加 overflow:hidden --><div style="overflow: hidden"><!-- 文本内容 --><div style="white-space: nowrap; overflow: hidden; text-overflow: ellipsis">LongTextLongTextLongTextLongTextLongTextLongText</div></div></div><div class="type-label">【有效】第三层 flex 容器【宽度固定】+ 第二层【min-width:0】 + 文本内容</div><!-- 第三层 --><div style="background: red; display: flex; width: 200px"><!-- 第二层宽度自适应,+ 增加 min-width:0 --><div style="display: flex; flex-grow: 1; overflow: hidden"><!-- 文本内容 --><div style="white-space: nowrap; overflow: hidden; text-overflow: ellipsis">LongTextLongTextLongTextLongTextLongTextLongText</div></div></div>
</div>
4.2 实际效果
4.3 总结
综上所述,解决 flex 布局中 text-overflow 无效的办法有两个:
- 给包含文本的标签的父元素增加 overflow: hidden 【常用】
- 给包含文本的标签的父元素增加 min-width: 0
还要注意,不要给文本内容的直接父元素设置成 flex 布局了,要不然就回到 3 中无效的场景了。
我常用第一种方法给包含文本的标签的父元素增加 overflow: hidden,因为我很好理解 hidden 的意思就是隐藏超出的文本部分,第二种方法增加一个最小宽度显得有点莫名其妙。
但是两种方法的本质都是一样的,overflow: hidden 的本质是设置了 min-width: 0。下面是 deepseek 给出的答案:
当 Flex 子项本身也是 Flex 容器时,若未显式设置
min-width: 0
,其默认min-width: auto
会阻止宽度收缩父容器的宽度约束会直接影响子元素的可用空间。只有父容器允许收缩(
min-width: 0
),子元素的min-width: 0
才能生效。
虽然我常用 overflow:hidden 但是使用 min-width 确实不会有啥副作用,大家看自己喜欢选择。
5. 完成 vue 代码
<template><div class="page-wrapper"><div>内容过长省略号的三个属性(给文本内容的直接父元素增加):</div><ol><li>white-space: nowrap;</li><li>overflow: hidden;</li><li>text-overflow: ellipsis;</li></ol><div class="block-wrapper"><div class="label">类型一:块元素/行内元素/行内块元素【直接包含文本内容】</div><div class="type-label">【有效】不设置宽度 + 单个【块元素】标签</div><div style="background: red; white-space: nowrap; overflow: hidden; text-overflow: ellipsis">LongTextLongTextLongTextLongTextLongTextLongText</div><div class="type-label">【有效】不设置宽度 + 单个【行内元素】标签</div><span style="background: red; white-space: nowrap; overflow: hidden; text-overflow: ellipsis">LongTextLongTextLongTextLongTextLongTextLongText</span><div class="type-label">【有效】不设置宽度 + 单个【行内块元素】标签</div><div style="display: inline-block; background: red; white-space: nowrap; overflow: hidden; text-overflow: ellipsis">LongTextLongTextLongTextLongTextLongTextLongText</div></div><div class="block-wrapper"><div class="label">类型二:flex 布局的子项目【包含文本内容】</div><div class="type-label">【有效】flex 容器【宽度固定】 + 块级元素子项</div><div style="background: red; display: flex; width: 200px"><!-- div 块元素 --><div style="white-space: nowrap; overflow: hidden; text-overflow: ellipsis">LongTextLongTextLongTextLongTextLongTextLongText</div></div><div class="type-label">【有效】flex 容器【宽度固定】+ 行级元素子项</div><div style="background: red; display: flex; width: 200px"><!-- span 行内元素 --><span style="white-space: nowrap; overflow: hidden; text-overflow: ellipsis">LongTextLongTextLongTextLongTextLongTextLongText</span></div><div class="type-label">【有效】flex 容器【宽度固定】+ 子项手动设为行内元素</div><div style="background: red; display: flex; width: 200px"><!-- 手动设为行内元素--><div style="display: inline; white-space: nowrap; overflow: hidden; text-overflow: ellipsis">LongTextLongTextLongTextLongTextLongTextLongText</div></div><div class="type-label">【有效】flex 容器【宽度固定】+ 子项手动设为行内块元素</div><div style="background: red; display: flex; width: 200px"><!-- div 作为flex项目,又设置为 inline-block 元素 --><div style="display: inline-block; white-space: nowrap; overflow: hidden; text-overflow: ellipsis">LongTextLongTextLongTextLongTextLongTextLongText</div></div><div class="type-label">【有效】flex 容器【宽度固定 百分比】+ 子项手动设为行内元素</div><div style="background: red; display: flex; width: 100%"><div style="display: inline; white-space: nowrap; overflow: hidden; text-overflow: ellipsis">LongTextLongTextLongTextLongTextLongTextLongText</div></div><div class="type-label">【有效】flex 容器【宽度固定 vw】+ 子项手动设为行内元素</div><div style="background: red; display: flex; width: 20vw"><div style="display: inline; white-space: nowrap; overflow: hidden; text-overflow: ellipsis">LongTextLongTextLongTextLongTextLongTextLongText</div></div><div class="type-label error">【无效】flex 容器【宽度固定 vw】+ 子项手动设为 flex 布局</div><div style="background: red; display: flex; width: 20vw"><div style="display: flex; white-space: nowrap; overflow: hidden; text-overflow: ellipsis">LongTextLongTextLongTextLongTextLongTextLongText</div></div></div><div class="block-wrapper"><div class="label">类型三:三层结构以上 flex 布局</div><div class="type-label error">【无效】第三层 flex 容器【宽度固定】+ 第二层宽度自适应 + 文本内容</div><!-- 第三层 --><div style="background: red; display: flex; width: 200px"><!-- 第二层宽度自适应,不做任何处理 --><div><!-- 文本内容 --><div style="white-space: nowrap; overflow: hidden; text-overflow: ellipsis">LongTextLongTextLongTextLongTextLongTextLongText</div></div></div><div class="type-label error">【无效】第三层 flex 容器【宽度固定】+ 第二层宽度自适应【flex-grow】 + 文本内容</div><!-- 第三层 --><div style="background: red; display: flex; width: 200px"><!-- 第二层宽度自适应 --><div style="display: flex; flex-grow: 1"><!-- 文本内容 --><div style="white-space: nowrap; overflow: hidden; text-overflow: ellipsis">LongTextLongTextLongTextLongTextLongTextLongText</div></div></div><div class="type-label">【有效】第三层 flex 容器【宽度固定】+ 第二层【overflow:hidden】 + 文本内容</div><!-- 第三层 --><div style="background: red; display: flex; width: 200px"><!-- 第二层宽度自适应,增加 overflow:hidden --><div style="overflow: hidden"><!-- 文本内容 --><div style="white-space: nowrap; overflow: hidden; text-overflow: ellipsis">LongTextLongTextLongTextLongTextLongTextLongText</div></div></div><div class="type-label">【有效】第三层 flex 容器【宽度固定】+ 第二层【min-width:0】 + 文本内容</div><!-- 第三层 --><div style="background: red; display: flex; width: 200px"><!-- 第二层宽度自适应,+ 增加 min-width:0 --><div style="display: flex; flex-grow: 1; overflow: hidden"><!-- 文本内容 --><div style="white-space: nowrap; overflow: hidden; text-overflow: ellipsis">LongTextLongTextLongTextLongTextLongTextLongText</div></div></div></div></div>
</template>
<style lang="scss" scoped>
.page-wrapper {display: flex;flex-direction: column;padding: 20px;gap: 10px;.block-wrapper {display: flex;flex-direction: column;padding: 20px;width: 100%;border: 1px solid #ccc;border-radius: 4px;.label {font-size: 16px;font-weight: bold;}.type-label {margin: 10px 0 0;&.error {color: red;}}}
}
</style>