配了八年字体,每次 fallback 都要靠计算器——Chrome 127 把 aspect ratio 这件事彻底原生化了
换字体的时候有没有遇到过这种情况:font-size 明明一样,视觉上却大了一号?
这不是你的错觉。Verdana 的 aspect value(x-height / font-size)是 0.58,Times New Roman 是 0.46。设 16px,Verdana 的小写字母实际只有 9px 高,而 Times New Roman 只有 7px——差了整整 2px,肉眼非常明显。
以前只有 Firefox 认真支持这个属性,Chrome/Safari 都爱答不理。Chrome 127 把这件事彻底变了:font-size-adjust 现在是全功能状态,而且迎来了两值语法。
核心问题:fallback 字体的大小失真
CSS font-family 按顺序找字体,找到哪个用哪个。第一个字体没加载完时,浏览器会用 fallback 渲染,而这个 fallback 和你的主字体看起来大小完全不同。
根本原因是每个字体的 aspect value 不一样。Aspect value = x-height(字母 “x” 的高度)/ font-size。Verdana 约 0.58,Georgia 约 0.46,Roboto 约 0.5——同一个 font-size,不同字体的小写字母高度差 10% 以上。
旧方案:手动计算校正值
在没有 font-size-adjust 的年代,你要自己算:
body {
font-size: 16px;
}
.fallback-text {
font-family: "Roboto", "Arial", sans-serif;
font-size: 16px;
/* Verdana aspect: 0.58, Arial aspect: 0.46
校正: 16 * (0.58 / 0.46) ≈ 20px
但这个值是硬算的,换字体又要重算 */
}
问题是:你不知道下一个 fallback 的 aspect value,动态字体加载更是无从算起。
font-size-adjust 的解题思路
font-size-adjust 的思路是:告诉浏览器用哪个度量标准来校准字体大小。
单值语法(已有多年)
/* 告诉浏览器:按 x-height = 0.5 的比例校准 */
font-size-adjust: 0.5;
这意味着:实际渲染时,浏览器会让 x-height = font-size × 0.5。不同字体通过调整 font-size 来满足这个比例,从而视觉大小一致。
两值语法(Chrome 127 新增)
这是关键升级。现在可以明确指定用哪个度量:
/* 按 x-height(字母 x 的高度)校准,比例从字体本身读取 */
font-size-adjust: ex-height from-font;
/* 按大写字母高度校准 */
font-size-adjust: cap-height from-font;
/* 按数字 0 的宽度校准(适合等宽场景) */
font-size-adjust: ch-width from-font;
/* 按 CJK 水字宽度校准(适合中日韩字体混排) */
font-size-adjust: ic-width from-font;
from-font 关键字让浏览器直接读取第一个可用字体的度量值,不需要你手动查表。
实战:设计系统字体回退
:root {
--body-font: "Inter", "Noto Sans SC", sans-serif;
--base-size: 1rem;
}
/* 校准到 Inter 的 x-height 比例 */
body {
font-family: var(--body-font);
font-size-adjust: ex-height 0.5; /* Inter 的 x-height 约为 0.5 */
font-size: var(--base-size);
}
/* fallback 字体自动校准到相同视觉大小 */
p, li, td {
/* 不需要重复写 font-size-adjust,会继承 */
}
真实数据:Inter(aspect 0.52)→ fallback 到 system-ui(aspect 0.48)时,16px 会自动校正到约 17px(16 × 0.52/0.48),视觉大小几乎不变。
浏览器支持:终于到齐了
| 浏览器 | 单值语法 | 两值语法(ex-height 等) |
|---|---|---|
| Chrome | 127+ | 127+ ✅ |
| Edge | 127+ | 127+ ✅ |
| Firefox | 3+ | 92+ |
| Safari | 16.4+ | 17+ |
| Safari iOS | 16.4+ | 17+ |
全球覆盖率约 94%。给不支持的浏览器一个 fallback 即可:
body {
font-family: "Inter", system-ui, sans-serif;
font-size-adjust: ex-height from-font;
font-size: 1rem;
}
/* 不支持的浏览器忽略 font-size-adjust,用原始 font-size */
三个坑
1. @font-face 自定义字体的 aspect value
from-font 只读取系统字体度量。如果你的 Web Font 没有内置正确的度量数据,用显式数字更可靠:
/* 自定义字体不知道 aspect,手动指定 */
font-size-adjust: ex-height 0.52; /* 测量 Inter 的 x-height 得来 */
2. 只影响 fallback,不影响主字体
font-size-adjust 只对不在首选位置的字体生效。如果你声明的 font-family 第一个就命中了,font-size-adjust 不起作用。这是设计逻辑,不是 bug。
3. 调整的是 font-size,不是 x-height 本身
font-size-adjust 的本质是:当字体 fallback 时,临时增大该字体的 font-size 使其 x-height 匹配目标值。如果你对文字容器高度有精确约束,需要额外注意。
三步下一步
-
测当前 fallback 情况:打开 DevTools Elements 面板,临时把 font-family 改成只有 fallback 字体,看文字大小是否明显变化。如果变了,就该上 font-size-adjust。
-
找到你的基准 aspect value:Chrome DevTools Font 面板可以量 x-height。找到主字体的 x-height / font-size 作为基准值。
-
加到全局:
:root { font-size-adjust: ex-height <你的值>; }一行解决所有 fallback 字体失真问题。
Chrome 127 把 font-size-adjust 做成全功能,意味着前端工程师终于可以在生产环境里用它了。八年 CSS,用过的人不多,不是因为它没用,而是因为浏览器支持一直在拖后腿。现在腿没了。
评论区
登录后可评论。