减少跳动:后备字体和尺寸调整
适合谁看:用了
font-display: swap,但字体换上来时页面「跳一下」,想减少布局偏移(CLS)的开发者。
为什么会跳
备用字体和网页字体的字宽、上下留白不同。换字体时,一行能放下的字数变了,行高也可能变了,后面的内容就整体移动。
对中文来说:
- 汉字基本都是等宽的方块,中文部分的字宽差别不大;
- 差别主要来自西文、数字、标点的宽度,以及行高;
- 如果没有写死
line-height,浏览器按字体自带的上下高度计算行高(line-height: normal),换字体后每行高度都可能变化。
第一步:写死行高
给正文写一个明确的行高,行高就不再依赖字体:
body { line-height: 1.75; }
这是最简单、效果最明显的一步。排版上的行高建议见《正文用字:字号、行距和字重》。
第二步:选接近的备用字体
备用字体和网页字体越接近,跳动越小:
- 黑体类网页字体,备用写系统黑体(苹方、微软雅黑、思源黑体 / Noto Sans CJK);
- 宋体、楷体、仿宋类,备用写系统同类字体,见《中文字体栈怎么写》。
第三步:用尺寸调整描述符微调
可以为备用字体单独写一条 @font-face,用描述符把它「调」得更像网页字体:
@font-face {
font-family: "My Sans Fallback";
src: local("PingFang SC Regular"), local("Microsoft YaHei");
size-adjust: 100%;
ascent-override: 88%;
descent-override: 12%;
line-gap-override: 0%;
}
body { font-family: "My Sans", "My Sans Fallback", sans-serif; }
| 描述符 | 调整什么 |
|---|---|
size-adjust |
整体缩放字形[1] |
ascent-override |
基线以上的高度 |
descent-override |
基线以下的高度 |
line-gap-override |
行间额外空隙 |
上例中的百分比只是示意,要按两款字的实际度量计算。
浏览器支持情况(据 MDN 兼容性数据):size-adjust 在 Chrome 92、Firefox 92、Safari 17 起支持;起支持[2];ascent-override 等三项在 Chrome 87、Firefox 89 起支持,Safari 正式版尚未支持。正式版尚未支持[3]。不支持的浏览器会忽略这些描述符,不会出错。
怎么量
- Chrome 开发者工具「性能」面板,或 Lighthouse,查看 CLS(累计布局偏移)[4];
- 对比开启和关闭网页字体时的截图。
参考资料
参考资料(4)
MDN:size-adjust:https://developer.mozilla.org/en-US/docs/Web/CSS/Reference/At-rules/@font-face/size-adjust