font-display: swap 是第三方字体按需加载的底线配置,可避免FOIT,确保系统字体立即渲染并平滑替换;需配合preload(带crossorigin等属性)、@font-face声明及字体子集化三者协同生效。

font-display: swap 是第三方字体按需加载的底线配置
不加 font-display,浏览器默认行为等同于 font-display: block:文字先隐形 100ms,再最多等 3 秒加载字体,失败才 fallback——这就是用户看到的 FOIT(Flash of Invisible Text)。对内容型页面,这等于主动牺牲首屏可读性。
实际项目中,swap 是最稳妥的选择:系统字体立刻渲染,字体加载完后无感替换。注意两点:
-
swap可能引发轻微重排(比如 Inter Regular 和系统 Arial 字宽不同),但比白屏或闪动更可接受 - 别误用
optional:它会让浏览器跳过加载(除非缓存命中),适合装饰性标题字,不适合正文
preload 关键字体必须带 crossorigin 属性
仅写 是无效的——浏览器会忽略该请求。必须同时满足三项:
-
as="font"告诉浏览器这是字体资源 -
type="font/woff2"明确 MIME 类型,避免复用失败 -
crossorigin属性不可省略,即使字体同源;缺了它,preload 就不生效
只预加载首屏确定要用的字重,比如标题用 Inter-Bold,就只 preload 它,别把 Inter-Regular、Inter-Italic 全塞进去。
@font-face 必须与 preload 共存,不能只靠 preload
只负责提前下载,不声明字体可用性;@font-face 才是让 CSS 能通过 font-family 调用它的关键。漏掉任一环节,字体就无法渲染。
常见错误是以为 preload 后就可以删掉 @font-face 声明,结果 DevTools 的 Elements 面板里 font-family 计算值始终是 sans-serif。正确写法是两者并存:
@font-face {
font-family: 'Inter';
src: url('/fonts/inter-bold.woff2') format('woff2');
font-weight: 700;
font-display: swap;
}
且确保 font-family 名称在 CSS 使用处和 @font-face 中完全一致(大小写、空格、连字符)。
字体文件本身要按需拆分,不是靠 JS 判断
所谓“按需”,95% 场景发生在构建阶段,不是运行时。一个 Inter-Variable.woff2 文件可能 300KB,但页面只用 Regular + Bold 两个字重,且只显示英文数字——这时候 JS 检测屏幕宽度或语言毫无意义。
实操建议:
- 用
pyftsubset(fonttools)生成 ASCII 子集,体积常压到原文件 20% 以内 - 把不同字重拆成独立文件:
inter-regular.woff2、inter-bold.woff2,CSS 中按需引用 - 避免在单个 @font-face 中用
font-weight: 100 900声明整个区间——浏览器会尝试加载所有字重变体
视觉展位设计的关键,其实是让文字在字体加载前后都保持可读、不跳动、不缩放。swap + preload + 子集化三者缺一不可,而最容易被跳过的,是子集化——它不写在 HTML 或 CSS 里,却直接决定首屏字体资源的大小和加载耗时。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











