多行省略号那套 -webkit-box 写法,其实是十年前一个内核私有 hack,今天终于进标准了
卡片里那行「…」,你写了十年的 display: -webkit-box + -webkit-line-clamp,其实从来不是标准写法——它是 WebKit 十几年前为多行 flexbox 顺手留的一个私有实现。今天这件事有了正式名字:line-clamp。
先说结论
line-clamp 是 CSS Overflow Module Level 4 里正式的标准属性,Applies to 明确写着 block containers except multi-column containers。它跟 -webkit-line-clamp 不是「换个名字」的关系,而是一次从内核私有 hack 到标准长属性的重构:
-webkit-line-clamp只在display: -webkit-box(或-webkit-inline-box)+-webkit-box-orient: vertical这三个属性绑成一串时才生效;- 标准的
line-clamp作用在块容器上——<p>、<div>这些你平时写正文的普通元素就能用,不必把自己伪装成 flex box。
换句话说,过去那句「必须配 -webkit-box」不是 CSS 的规则,是那个私有实现的副产品。
为什么以前那套写法这么别扭
想想你现在项目里的代码,大概率长这样:
.card-excerpt {
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-line-clamp: 3;
overflow: hidden;
}
四个属性缺一不可,漏掉任何一个,截断就静默失效——不报错,只是那个「…」不出现。这是它最坑人的地方:
display: -webkit-box改变了布局模型。你的元素从普通块变成了一行 flex container。里面如果再放<span>、<a>、<strong>,排版行为会跟着变,图片、按钮放进这个容器经常出现奇怪的收缩。overflow: hidden不能省。省掉的话浏览器照样算「第 3 行在哪」,但溢出的文字不会裁掉,只是多一个「…」挂在那里。- 压缩工具会把
-webkit-box-orient: vertical当无用属性删掉。autoprefixer 等工具需要特意配置保留它,否则线上就是没效果——这个坑在 issue 里躺了很多年。
正因为 line-clamp 不依赖 -webkit-box,上面三条里最麻烦的第 1 条直接消失了:块容器本来就是块容器。
标准属性给了你哪些以前没有的能力
按规范(CSS Overflow Module Level 4 第 5.1 节),line-clamp 其实是三个长属性的简写:
| 简写 | 拆成 | 含义 |
|---|---|---|
max-lines |
截断到第几行 | 与老的 -webkit-line-clamp 数值对应 |
block-ellipsis |
末行插入什么 | auto / no-ellipsis / 自定义字符串 |
continue |
是否折叠溢出内容 | collapse / auto / -webkit-legacy |
三个变化值得单独拎出来:
一是省略号内容可以自定义。 规范里的例子是:
li {
line-clamp: 5 "… (continued on next page)";
}
末行不是固定的「…」,而是你想要的那段文字。这在「未完待续」「展开全文」这类场景里,终于不用再拿 ::after 伪元素去绝对定位盖一层了。
二是可以明确不要省略号。 line-clamp: 3 no-ellipsis 表示我只想截三行,但别给我加那个字符——以前 -webkit-line-clamp 做不到这一点,只能靠外层再套一层容器骗过去。
三是内容和测量一起消失。 规范原话是 remaining content is fragmented away and neither rendered nor measured(既不渲染也不参与测量)。这对搞性能的人是好事——被截掉的段落不会再去参与高度计算和后续布局。
现实里的浏览器支持,别急着删老写法
这里必须说清楚,规范是规范,上线是上线。根据 caniuse 当前的兼容数据:
-webkit-line-clamp表格:Chrome 14+、Firefox 68+、Safari 5+ 全线支持,全球覆盖率约 97%,已经进 Baseline;- 无前缀的
line-clamp表格:Chrome 6–152 标记为支持,但 Firefox 是 156 起才默认打开(更早版本需要layout.css.line-clamp.enabled这个 flag,所以unprefixed这一格的覆盖率只有 0.19%),Safari 5–18.1 这段还有个更早历史实现的标注。
翻译成人话:写得对的代码应该同时留两行。
.card-excerpt {
/* 兜底:所有现存浏览器都能跑 */
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-line-clamp: 3;
overflow: hidden;
/* 标准:写法对齐规范,等支持面铺开就能删上一段 */
-webkit-line-clamp: 3; /* WebKit 也仍然认这个 alias */
line-clamp: 3;
}
渐进式的做法更稳妥:
/* 先按块容器写标准属性,能生效的浏览器直接用 */
.card-excerpt {
line-clamp: 3;
overflow: hidden;
/* 不支持的浏览器靠 @supports 补老的私有写法 */
@supports not (line-clamp: 3) {
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-line-clamp: 3;
}
}
今天的下一步
不用大改,三件事,二十分钟能做完:
- 全局搜一遍
-webkit-line-clamp,把每一处的用途记下来:是「多行截断」还是「其实是单行截断」。单行截断压根不需要它,white-space: nowrap+text-overflow: ellipsis就够了,能删一批。 - 给卡片截断加一条无前缀声明。哪怕浏览器还没全支持,把标准写法写进代码库,等工具链的 autoprefixer 和新版浏览器跟上,它就是免费收益。
- 检查构建配置,确认
-webkit-box-orient: vertical在压缩后没有被删掉——这是老写法线上失效最常见的原因,顺手确认一下@supports包裹有没有被 eslint 或 postcss 误处理。
line-clamp 的价值不在「多了一个属性」。它把一件本来只能靠内核私有 hack 达成的事,变成了可以写在规范里、可以被 @supports 查询、可以带自定义省略号的功能。这一步走完,前端处理截断这件事才算真正有了标准答案。
评论区
登录后可评论。