配了多年 CSS 行高,今天才知道 line-height: calc() 这种写法一直是无效的——Safari STP 158 把这件事彻底修对了
配了多年 CSS 行高,今天才知道 line-height: calc() 这种写法一直是无效的——Safari STP 158 把这件事彻底修对了
写过 CSS 行高体系的工程师都踩过这个坑:line-height 想用百分比(相对 font-size)和固定长度(em/px)组合,算出来一个既有相对弹性又有固定增量的值。以前 calc() 在 line-height 里根本不能这么用,要么只能写死 1.5(纯数字),要么只能写百分比,写 calc(100% + 0.5em) 浏览器直接忽略。今天 Safari Technology Preview 158(WebKit r256095)改了 line-height 的解析规则,允许 calc() 组合百分比和长度单位——这个十年未变的限制终于松动了。
以前的限制
/* 这些以前都是无效的,浏览器直接忽略 */
line-height: calc(100% + 0.5em); /* ❌ 不支持 */
line-height: calc(1.5 * 1em + 4px); /* ❌ 不支持 */
/* 只能这样写 */
line-height: 1.5; /* 纯数字,1.5 × font-size */
line-height: 150%; /* 纯百分比,相对 font-size */
/* 想加一个固定值?没有直接办法 */
/* 必须靠 line-height: 1.5; padding-top: 2px; */
/* 或者用 ::first-line 伪元素 hack */
line-height: calc(100% + 0.5em) 想表达的意思是「行高 = 一行文字的高度(相对 font-size)加上固定的上下行间距(绝对值)」,这对精密的排版系统来说很常见。
今天 calc() 组合成为可能
Safari STP 158 修改了 line-height 的 computed value 算法,现在允许百分比和长度单位在 calc() 内组合:
/* 新的合法写法 */
line-height: calc(100% + 0.5em); /* 基准行高 + 固定间距 */
line-height: calc(1.5 * 1em + 4px); /* 乘数 + 固定值 */
line-height: calc(100% + 0.5em); /* Safari STP 158+ */
line-height: calc(2 * 1em + 1px); /* 双倍行高 + 1px 修正 */
/* 结合自定义属性 */
html {
--base-leading: 0.5em;
--line-height-ratio: 1.6;
}
body {
line-height: calc(var(--line-height-ratio) * 1em + var(--base-leading));
}
典型使用场景:
/* 中文排版:行高基准 + 固定行间距 */
p.cn-text {
/* 行高 = 1.8 × font-size,再加 4px 固定行距 */
line-height: calc(180% + 4px);
}
/* 精密 UI:按钮行高固定,上下 padding 决定高度 */
button {
/* 文字行高固定为 1em,padding 实现高度 */
line-height: calc(1em);
padding: calc(0.5em) 1em; /* calc 也可以用于 padding */
}
/* 多语言:不同语言设不同行高基准,统一加固定增量 */
:lang(en) {
line-height: calc(1.5 * 1em + 2px);
}
:lang(zh) {
line-height: calc(1.7 * 1em + 2px); /* 中文行距需要更大 */
}
规范变化解释
旧算法:line-height 的 computed value 只能是数字(无单位)或百分比(相对 font-size),两者不能混合。
新算法:line-height 的 computed value 允许 calc() 表达式,且 <calc-constant> 的 number 可以和 <length-percentage> 混合——<length-percentage> 本身包含百分比(相对 font-size)和长度(em/px)两个分量。
/* 以下现在都合法 */
line-height: calc(1.5); /* 数字的 calc */
line-height: calc(100%); /* 纯百分比 */
line-height: calc(100% + 1em); /* 百分比 + 长度 */
line-height: calc(1.5 * 1em + 4px); /* 乘数 + 长度 */
line-height: calc(100% + var(--gap)); /* 百分比 + 自定义属性 */
浏览器支持
| 浏览器 | 支持情况 |
|---|---|
| Safari | Safari STP 158+(本功能) |
| Safari 稳定版 | ❌ 尚未支持 |
| Chrome | ❌ 暂无信号 |
| Firefox | ❌ 暂无信号 |
WebKit r256095 是首个将
calc()组合能力引入line-height的实现,Chrome 和 Firefox 的支持状态需要观察。渐进增强:旧浏览器会忽略calc()表达式,退回line-height: 1.5(默认值)。
三步落地
- 替换固定行高 hack:把
line-height: 1.5; padding: X合并为line-height: calc(1.5 * 1em + X) - 设计系统变量化:把
line-height的比例和固定增量分离为两个 CSS 变量,按语言/组件分别调整 - 降级兜底:
@supports (line-height: calc(100% + 0px))做特性检测,未支持浏览器用纯数字写法
/* 特性检测 */
@supports (line-height: calc(100% + 0em)) {
p {
line-height: calc(180% + 4px); /* 新语法 */
}
}
/* 不支持时降级 */
@supports not (line-height: calc(100% + 0em)) {
p {
line-height: 1.5; /* 退回到纯数字 */
}
}
line-height: calc() 允许组合百分比和长度,这个变化的本质是把「行高」从「一个固定比例值」变成「一个可组合的表达式」。对中文排版、精密 UI 设计和多语言设计系统来说,这是期待已久的能力——终于可以用一个声明同时表达「相对字号的弹性」和「固定的行间距修正」了。
评论区
登录后可评论。