多行省略号那套 -webkit-box 写法,其实是十年前一个内核私有 hack,今天终于进标准了

卡片里那行「…」,你写了十年的 display: -webkit-box + -webkit-line-clamp,其实从来不是标准写法——它是 WebKit 十几年前为多行 flexbox 顺手留的一个私有实现。今天这件事有了正式名字:line-clamp

先说结论

line-clampCSS 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;
}

四个属性缺一不可,漏掉任何一个,截断就静默失效——不报错,只是那个「…」不出现。这是它最坑人的地方:

  1. display: -webkit-box 改变了布局模型。你的元素从普通块变成了一行 flex container。里面如果再放 <span><a><strong>,排版行为会跟着变,图片、按钮放进这个容器经常出现奇怪的收缩。
  2. overflow: hidden 不能省。省掉的话浏览器照样算「第 3 行在哪」,但溢出的文字不会裁掉,只是多一个「…」挂在那里。
  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;
  }
}

今天的下一步

不用大改,三件事,二十分钟能做完:

  1. 全局搜一遍 -webkit-line-clamp,把每一处的用途记下来:是「多行截断」还是「其实是单行截断」。单行截断压根不需要它,white-space: nowrap + text-overflow: ellipsis 就够了,能删一批。
  2. 给卡片截断加一条无前缀声明。哪怕浏览器还没全支持,把标准写法写进代码库,等工具链的 autoprefixer 和新版浏览器跟上,它就是免费收益。
  3. 检查构建配置,确认 -webkit-box-orient: vertical 在压缩后没有被删掉——这是老写法线上失效最常见的原因,顺手确认一下 @supports 包裹有没有被 eslint 或 postcss 误处理。

line-clamp 的价值不在「多了一个属性」。它把一件本来只能靠内核私有 hack 达成的事,变成了可以写在规范里、可以被 @supports 查询、可以带自定义省略号的功能。这一步走完,前端处理截断这件事才算真正有了标准答案。

评论区

0 条评论

登录后可评论。