跳到正文

单行省略为什么会裁掉字:line-height、字形和 overflow 的边界

昵称和表格单元格常用单行省略。有时省略号正常出现,字母底部或重音却少了一截。开发者容易先改宽度,甚至换成 JavaScript 截字符串;真正需要看的往往是行高和裁切区域。

省略号只处理行内溢出

常见的 truncate 对应 overflow: hidden、text-overflow: ellipsis 和 white-space: nowrap。它解决的是横向空间不足,没有承诺字形在垂直方向一定完整。text-overflow 文档也将它限定在行内方向。

line-height: 1 则让行高等于当前字号,但字形的实际绘制范围未必落在这个高度内。字体、fallback、多语言和重音组合都会影响绘制范围;裁切生效后,超出区域的部分就可能不可见。行高值的计算方式可对照 line-height 文档。

这不是说所有字体的 g 在行高 1 时都必然被裁。某个字体、字号和浏览器刚好正常,不能证明换成用户真实文本后仍然安全。

文本行高与控件高度分开调整

.name {
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
  line-height: 1.4;
}

1.4 只是 demo 的起点,应按设计和真实字体复核。不要把 1.2 或某个 utility 当成通用安全阈值。若设计要求按钮紧凑,用外层的 padding、min-height 和对齐控制控件高度,给文本保留足够的行盒高度;只把垂直 padding 加到外层、内层仍然裁切,也未必能补回字形。

把真实文本放进浏览器比较

下面的 demo 可以调整风险行的行高,修改文本,并与行高 1.4 的参考行比较。默认样例包含下探笔画和叠加重音,目的是暴露边界,不代表任何特定业务数据。

读取 https://shengsheng.fun/files/truncate-line-height-glyph-clipping/kits/text-clipping-demo/ 的 README.md 和 FILES.json,打开 index.html。替换为项目字体和真实文本,检查完整字形与省略号。
单行省略为什么会裁掉字:line-height、字形和 overflow 的边界正在加载代码工作区...

同一字体与文本在不同文本行高下的浏览器比较

验收时至少覆盖普通拉丁字母、中文、项目涉及的复杂文字和 emoji,检查字体加载前后、小字号、窄容器和浏览器缩放。需要固定高度的地方,再检查实际 height、max-height、transform 与祖先 overflow,避免只修了一个行高。

规则只能提示可疑组合

Vue 模板或 utility 字符串可用 @sheng/ui-no-truncate-leading-none;样式 AST 可用 sheng/no-truncate-leading-none。后者检查 CSS 需要正确的 Stylelint customSyntax,不能拿它扫描模板 class 字符串。

两条规则都用于提前提示常见高风险组合,不能根据 AST 计算最终字体的字形边界。跨 class 组合、继承、动态样式和祖先裁切仍要实际渲染。确有已验证的紧凑排版时,可以按范围配置例外;发布前保留对应字体与文本的截图回归。