前端知库

单行和多行文本省略怎么写?

单行省略要同时写 white-space: nowrap、overflow: hidden 和 text-overflow: ellipsis,元素还要有确定的宽度。多行省略目前通用写法是 display: -webkit-box、-webkit-box-orient: vertical 加 -webkit-line-clamp,再配 overflow: hidden。标准的 line-clamp 属性浏览器支持还有限。

参考答案

简答

商品标题太长,列表里只显示一行,末尾用省略号。单行要写三条:white-space: nowrap 不让文字换行,overflow: hidden 把超出的部分藏起来,text-overflow: ellipsis 在被截断的地方显示省略号。元素本身要有确定的宽度,比如块元素或者设了 width、max-width。

为什么要三条一起写?MDN 的说明是,text-overflow 只负责“怎样提示内容溢出了”,它不会让文字溢出,要靠 overflow 和 white-space 让文字溢出并隐藏。而且它只处理行内方向的溢出,所以管不了多行。

多行省略目前通用的写法是带 -webkit- 前缀的一组:display: -webkit-box、-webkit-box-orient: vertical、-webkit-line-clamp: 2,再加 overflow: hidden。MDN 说明这个旧属性只在这种组合下生效。

要注意,标准的 line-clamp 属性已经写进规范,但浏览器支持还有限,现在还不能只写它。另外被截断的内容要有别的方式能看到,比如详情页或展开按钮。

单行省略

CSS
.title {
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

为什么常见的“只写了 text-overflow 没效果”?因为默认情况下文字会换行,不会溢出,也就没什么可提示的。white-space: nowrap 让文字挤在一行里溢出,overflow: hidden 让溢出部分不显示,text-overflow 才有机会把截断处换成省略号。

在 flex 布局里,省略常常失效,原因是 flex 子项默认的最小宽度是内容宽度,不会被压缩到比文字还窄。给这个子项加上 min-width: 0,它才能缩小,省略号才会出现。用 headless Chrome 实测,100px 宽的 flex 容器里,没加 min-width: 0 的子项被撑到 261px,加了以后是 100px。

多行省略

CSS
.desc {
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 2;
  overflow: hidden;
}

这组写法来自旧版的 WebKit 弹性盒,看起来奇怪。MDN 说明这几个带前缀的属性虽然已经废弃,但它们的配合方式已经完整写进规范,会一直被支持。-webkit-line-clamp 只有在 display 是 -webkit-box 或 -webkit-inline-box、并且 -webkit-box-orient 是 vertical 时才生效。

为什么还要 overflow: hidden?MDN 提醒,大多数情况下都要加,否则省略号会出现在第二行末尾,后面的内容却照样显示出来。用 headless Chrome 156 实测,16px 字号、20px 行高时,加不加 overflow: hidden,元素高度都是 40px,也就是两行;可是不加的话,后面几行文字会溢出到元素外面。

标准 line-clamp 现在能用吗

CSS Overflow 规范定义了不带前缀的 line-clamp,MDN 把它标为浏览器支持有限。在 Chrome 156 里,CSS.supports('line-clamp', '2') 返回 false,-webkit-line-clamp 返回 true,只写 line-clamp: 2 时文字不会被截断。所以现阶段多行省略还要写带前缀的那组,可以把标准写法一起写上,等浏览器支持后自动生效。

和标题的换行美化一起用的写法,见《text-wrap: balance 和 pretty 应该怎样使用?》。

常见追问

怎么判断文字有没有真的被截断?

在 JavaScript 里比较元素尺寸。单行看 scrollWidth > clientWidth,多行看 scrollHeight > clientHeight,成立就说明有内容被隐藏,可以据此决定要不要显示“展开”按钮。

省略号能放在中间吗,比如保留文件扩展名?

text-overflow 只能在行尾截断。保留扩展名一般把文件名拆成两段:前一段用单行省略,扩展名放在单独的元素里不收缩。