font-display: swap 必须写在 @font-face 规则内才生效,常见失效原因包括 src 缺 format 声明、@import 引入、file:// 协议 cors 拦截、相对路径错误;预加载需 crossorigin、as="font"、type 及路径与 @font-face 完全一致;fallback 字体应类型一致以减少 cls;document.fonts.ready 是字体真正就绪的可靠信号。

font-display: swap 必须写在 @font-face 里,否则无效
很多项目加了 font-display: swap 却没效果,根本不是浏览器不支持,而是它被忽略了。常见失效场景包括:
-
@font-face中src没声明format("woff2"),旧版 Safari 或 Edge 会跳过整条规则,退回到默认的block行为 - 用
@import引入字体 CSS,导致解析延迟、预加载失效 - 本地开发用
file://协议,字体请求被 CORS 静默拦截,font-display根本没机会生效 - 路径写成相对路径如
url(./fonts/Inter.woff2),构建后路径错位,资源 404
正确写法示例:
@font-face {
font-family: "Inter";
src: url("/fonts/Inter.woff2") format("woff2");
font-display: swap;
}
preload 字体必须带 crossorigin,且路径要和 @font-face 完全一致
<link rel="preload"> 不是加了就起作用。浏览器对字体资源有严格校验:
- 必须显式加
crossorigin属性——哪怕字体同源,WOFF2 加载强制走匿名跨域模式,缺它等于白写 -
as="font"和type="font/woff2"缺一不可;写成as="fetch"或漏掉type,Chrome 可能复用缓存但不触发字体解析 -
href必须和@font-face中src的路径完全一致(含查询参数,如?v=2.1),否则不复用缓存 - 只对
font-display: swap或optional生效;设成block时,预加载反而可能延长阻塞时间
正确写法示例:
<link rel="preload" href="/fonts/Inter.woff2" as="font" type="font/woff2" crossorigin>
fallback 字体链不能混用 serif 和 sans-serif
写了 font-display: swap 还看到文字“跳一下”,问题不在字体加载,而在 fallback 字体撑不开空间——这是典型的 CLS(累积布局偏移)。
- 避免混用
"Georgia"和"Inter":衬线 vs 无衬线,字宽差常超 20%,跳变明显 - 中文字体 fallback 要分平台写清楚:
"PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "Noto Sans CJK SC", sans-serif - 英文 fallback 优先用同类型链:
"Inter", "system-ui", -apple-system, BlinkMacSystemFont, "Segoe UI" - 别在外部 CSS 里用
font-size: 1.2em强制缩放——这会让 fallback 和 Web Font 基线错位
document.fonts.ready 才是字体真正可用的信号
font-display: swap 解决的是首次渲染,但 JS 动态插入文本、Canvas 绘制、SSR 水合后内容更新,仍可能因字体未真正就绪而回退到 fallback。
-
document.fonts.load("400 16px 'MyFont'")只检测该字重字号是否就绪,不保证所有变体(如 700、italic)都加载完成 - 多个字体需链式调用:
document.fonts.load("400 16px 'FontA'").then(() => document.fonts.load("700 16px 'FontB'")) - 真正代表“全部声明字体就绪”的是
document.fonts.ready,它返回 Promise,比单次load()更可靠 - Canvas 绘制前务必
await document.fonts.ready,否则context.font = "42px 'MyFont'"可能被忽略
最常被忽略的一点:字体闪烁的“视觉可接受性”不取决于技术是否配齐,而取决于 fallback 与目标字体在 x-height、cap-height、line-height 等度量值上是否足够接近——这些差异无法靠 JS 或 preload 消除,只能靠选型和微调。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











