做标题、按钮和卡片时,经常会遇到一个看似奇怪的现象:font-size 一样,文字上方和下方的空隙却不一样,调了 line-height 仍然要靠负边距“挤”位置。这个问题通常来自字体度量和行盒,而不是文字本身多了一行。
CSS 的 text-box-trim 用来选择裁剪文字盒的哪一侧,text-box-edge 用来指定对齐到大写字母顶端、基线等哪种字形边缘。想同时裁掉上下多余留白,可以从 text-box: trim-both cap alphabetic 开始,再用 @supports 给旧环境保留普通行高方案。
规范参考:https://www.w3.org/TR/css-inline-3/
text-box-trim只决定裁剪方向,text-box-edge决定文字盒参考边缘。trim-start、trim-end和trim-both分别对应上侧、下侧和两侧裁剪。- 新属性改变的是文字盒边界,不会自动消除组件自身的
padding;旧浏览器应保留可读的回退。
先还原文字盒上下留白不一致的症状
先把问题拆成三层:字体文件提供的度量,浏览器据此形成的行盒,以及组件额外设置的 padding。如果只改 line-height,往往是在改变整行高度,却没有明确说明文字应该贴近哪条字形边缘。
可以把 text-box-edge 看成“参照线”,把 text-box-trim 看成“裁剪哪边”。例如 cap alphabetic 让上边参考大写字母高度,下边参考字母基线;trim-both 再把两侧多出来的文字盒空间裁掉。padding 仍属于组件盒的内部空间,不能把它和文字盒裁剪混为一谈。
用 text-box-trim 和 text-box-edge 组合裁剪边缘
最小写法可以先从两个长属性开始。标题需要上下贴近字形时使用 trim-both;只想让文字靠近基线而保留顶部空间时使用 trim-end。不同字体的字形比例并不相同,所以这组声明适合解决“组件需要稳定文字边界”的问题,不代表所有字体都应使用同一组值。
.card-title {
/* 让文字盒上下两侧都参与裁剪,减少字体行盒的额外留白 */
text-box-trim: trim-both;
/* 上侧参考大写字母顶端,下侧参考字母基线 */
text-box-edge: cap alphabetic;
/* 组件自身空间仍单独控制,避免把 padding 当成文字盒留白 */
padding-block: 0.5rem;
}
.card-title--baseline {
/* 只裁掉字母基线下侧,保留上侧空间 */
text-box-trim: trim-end;
text-box-edge: cap alphabetic;
}
这两个属性的职责要分开记:裁剪方向写在 text-box-trim,参考边缘写在 text-box-edge。如果只写前者,浏览器仍会使用默认的边缘定义;如果只调整 padding,则只是移动组件内容,不会改变文字盒本身的参考关系。
用 text-box 简写并为旧环境保留回退
组件样式确定后,可以把两项声明合并成 text-box 简写。渐进增强的关键是先给旧浏览器一套正常可读的行高与内边距,再在支持新属性的环境里覆盖文字盒声明。这样新环境获得更紧的字形边界,旧环境也不会因为整条规则失效而变成不可读的窄盒。
.badge {
/* 旧环境先使用稳定的行高和盒内空间 */
line-height: 1.25;
padding-block: 0.45rem;
padding-inline: 0.75rem;
}
@supports (text-box-trim: trim-both) and (text-box-edge: cap alphabetic) {
.badge {
/* 支持时把文字盒裁剪到大写字母顶端与基线 */
text-box: trim-both cap alphabetic;
/* 新属性处理字形边界,保留横向 padding 负责按钮宽度 */
padding-block: 0.35rem;
}
}
@supports 只判断浏览器是否接受声明,不替你判断字体视觉是否合适。若项目包含多种字体,应在真实组件中重新设定 text-box-edge,并避免用固定负边距把某一种字体的效果硬套到所有语言。
字体、行高和内容变化时要留意什么
第一,裁剪文字盒不等于删除组件的 padding、边框或外边距;按钮仍要为点击区域和可读性保留足够空间。第二,trim-start 与 trim-end 适合只处理一侧对齐的场景,不能因为名称相近就把它们当成垂直居中工具。第三,动态内容换行后,行数和组件高度仍会变化,裁剪属性不会替你限制文本长度。
排查时按这个顺序看:先确认加载的是目标字体,再暂时去掉 padding 判断多余空间来自哪里,然后确认浏览器支持条件,最后分别比较 trim-start、trim-end 与 trim-both。如果旧浏览器没有这项能力,保留普通 line-height 是正常降级,不要用空白字符或负边距伪造相同效果。
相关问题
text-box-trim 会不会自动让按钮变矮? 不会。它主要改变文字盒的裁剪边界,按钮高度仍受行高、padding、边框和内容共同影响。
只写 text-box-edge 可以裁掉留白吗? 不能把它当成裁剪开关。它提供参考边缘,是否裁剪以及裁剪哪一侧由 text-box-trim 决定。
旧浏览器应该怎么处理? 先保留普通 line-height、padding 和可读的布局,再用 @supports 叠加新声明;不要让新属性成为唯一布局条件。

Popover API beforetoggle 怎样阻止不满足条件的浮层打开
