先记住这个答案
多行省略要四行一起写:display: -webkit-box 把元素变成老式弹性盒,-webkit-box-orient: vertical 让内容纵向排列,-webkit-line-clamp: 2 指定只显示两行并在第二行末尾放省略号,overflow: hidden 把后面的内容藏掉。它和单行省略的思路完全不同:单行是禁止换行再裁掉右侧,多行是允许换行、按行数截断。
-webkit-line-clamp要配纵向旧盒overflow: hidden负责把第三行以后藏起来- 多行省略不用
nowrap - 容器别加上下
padding,否则会露出半行
四行代码各管什么
先看一个卡片标题的写法,后面逐行拆。
.card-title {
display: -webkit-box; /* 老式弹性盒,line-clamp 只认它 */
-webkit-box-orient: vertical; /* 子内容纵向排列 */
-webkit-line-clamp: 2; /* 最多两行,第二行末尾出现 … */
overflow: hidden; /* 第三行以后不显示 */
line-height: 1.5;
word-break: break-all; /* 长英文单词、URL 也能断开 */
}-webkit-line-clamp 是 WebKit 早年给移动端做的私有属性,挂在 2009 年那一版弹性盒规范上。所以它离不开 display: -webkit-box 和 -webkit-box-orient: vertical,换成现代的 display: flex 就失效了。后来各家浏览器为了兼容都实现了这个带前缀的写法,现在主流浏览器都能用,这也是它看起来很怪却一直是标准答案的原因。
元素的高度会被算成两行的高度,文字在第二行末尾截断并补上省略号。overflow: hidden 必须有,line-clamp 本身不隐藏内容。
- 题目里说的「无 flexbox 或 grid」
- 这里容易误会。
-webkit-box是元素自己的display,和它的父元素是不是 flex 或 grid 没关系。父元素是 flex 容器时,这个标题照样能多行省略,只是如果它是 flex 子项,要记得给它min-width: 0或确定宽度,否则它会被内容撑宽,根本不换行。
和单行省略比,差在哪
单行省略的三件套是 white-space: nowrap、overflow: hidden 和 text-overflow: ellipsis:先不许换行,让文字在水平方向溢出,再把溢出部分替换成省略号。
多行省略恰好相反,必须允许换行。要是顺手把 white-space: nowrap 也写上,文字就只有一行,line-clamp 没东西可截。text-overflow 在多行方案里也用不上,省略号是 line-clamp 自己画的。
还有一个区别是省略号的位置。单行省略可以通过 direction 控制在哪一侧省略,多行省略只能在最后一行末尾。
容易答错的地方
- 给容器加上下
padding,底部露出半行字 line-clamp控制的是内容区高度,overflow: hidden裁的是内边距盒的边缘。容器有padding-bottom时,第三行的上半截会出现在内边距里。内边距加到外层包裹元素上,截断的那个元素只留文字。- 本地正常,打包后失效
- 有些构建链里的 Autoprefixer 会把
-webkit-box-orient当成过时前缀删掉,线上样式里只剩另外三行,省略就失效了。遇到这种情况先看产物 CSS 里这一行还在不在,在它前面加/* autoprefixer: ignore next */注释就能保住。 - 以为用
max-height就能替代 max-height: 3em加overflow: hidden只能把内容截成两行高,不会出现省略号,而且最后一行可能被拦腰截断。老方案会再用伪元素在右下角叠一个「…」,但文字短的时候省略号也会出现,需要 JS 配合判断。
面试官还会怎么问?
怎么判断文本到底有没有被截断,好决定要不要显示「展开」按钮?
比较元素的 scrollHeight 和 clientHeight。el.scrollHeight > el.clientHeight 说明有内容被藏起来了,这时再渲染展开按钮。要在字体加载完、元素宽度确定之后再测,窗口宽度变化时用 ResizeObserver 重新判断。
有没有不带前缀的标准写法?
规范里定义了不带前缀的 line-clamp 属性,目标是摆脱对 -webkit-box 的依赖,但浏览器支持还不整齐。生产环境目前仍然写带前缀的四行,要用新写法的话按 MDN 兼容表逐个确认目标浏览器。
展开和收起能做过渡动画吗?
直接在 -webkit-line-clamp: 2 和 none 之间切换是瞬间跳变,没有动画。常见做法是展开时先测出完整高度,用 max-height 做过渡,动画结束后再去掉 line-clamp;收起时反过来。
参考资料
示例用于理解所注明的运行环境与边界;延伸学习可结合原文中的更多案例。