配了多年 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(默认值)。

三步落地

  1. 替换固定行高 hack:把 line-height: 1.5; padding: X 合并为 line-height: calc(1.5 * 1em + X)
  2. 设计系统变量化:把 line-height 的比例和固定增量分离为两个 CSS 变量,按语言/组件分别调整
  3. 降级兜底:@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 设计和多语言设计系统来说,这是期待已久的能力——终于可以用一个声明同时表达「相对字号的弹性」和「固定的行间距修正」了。

评论区

0 条评论

登录后可评论。

铁锈·Rust工具链 77 阅读