font-display: fallback 是最稳的解法;它设100ms内用fallback显示、3s未加载完则放弃,避免重排闪动,在中文字体≥2MB及移动端兼容性最佳。

加 font-display: fallback 是最稳的解法,不是 swap,也不是 optional;它在移动端和中文字体场景下失效最少。
为什么 font-display: swap 在中文项目里反而容易闪得厉害
中文字体文件普遍 ≥2MB(尤其含常用汉字的 woff2),swap 会让浏览器“立刻用系统字体渲染 → 等字体加载完再替换”,但替换时机不可控:用户可能已读完首屏,字体才加载完,导致段落重排、按钮宽度突变、行高跳动——这不是没闪,是闪得更隐蔽、更难调试。
而 font-display: fallback 明确设定了两个时间阈值:
– 100ms 内必须用 fallback 字体显示(不白屏)
– 3s 内没加载完就彻底放弃(不强等、不重排)
- 这个行为在 iOS Safari 和 Android Chrome 上一致性高,不像
swap在旧版 Safari 下静默退化为block - 如果你的字体是标题专用(比如 logo 字体),才考虑
font-display: optional;正文/按钮/表单一律用fallback - 别信“swap 更友好”——那是英文小字体(fallback
@font-face 必须写的字段一个都不能少
漏掉 font-family 或 src,整条规则被浏览器忽略;写错 format() 值,Safari 直接跳过——它不报错,只沉默丢弃。
立即学习“前端免费学习笔记(深入)”;
-
font-family必须加英文引号,大小写、空格、连字符全要一致:'HarmonyOS Sans'≠HarmonyOS Sans≠"harmonyos sans" -
src路径以 CSS 文件位置为基准,不是 HTML 所在目录。例如 CSS 在/css/main.css,字体在/fonts/inter.woff2,就得写url('../fonts/inter.woff2') -
format('woff2')必须和实际后缀严格匹配:.woff2→'woff2',.ttf→'truetype',写成'ttf'或'woff'都会失效 - 每个字重(400 / 500 / 700)和每种样式(
normal/italic)都要单独写一条@font-face,不能共用font-family名却只给其中一条加font-display
<link rel="preload"> 不带 crossorigin 就等于没写
没 preload,font-display: fallback 的 100ms 渲染窗口可能刚过,字体请求才发起——用户已经滑走了,字体还在 DNS 查询阶段。
但 preload 错一个属性就静默失败:Network 面板里根本看不到请求,控制台也不报错。
- 必须同时满足:
as="font"(不能是"fetch"或留空)、crossorigin属性(值可为空:crossorigin="")、type="font/woff2" -
href路径必须和@font-face中src的 URL 完全一致:协议、域名、路径、查询参数都不能差。比如预加载/fonts/inter-bold.woff2?ver=2,但 CSS 里写的是url('./fonts/inter-bold.woff2'),复用就失败 - 字体托管在 CDN 或 SaaS 服务上时,漏掉
crossorigin会导致响应被 CORS 策略丢弃,控制台报CORS error,且后续@font-face加载也会失败
fallback 字体链不匹配是抖动的真正元凶
启用 font-display: fallback 后,系统字体和 Web 字体的 metrics(字号、字宽、x-height、line-height)差异会引发文字重排。这不是 bug,是必然现象。
- 避免用泛泛的
sans-serif作 fallback:它在 Windows/macOS/iOS 上对应不同字体(Segoe UI / San Francisco / PingFang),宽度差异极大 - 显式指定度量接近的 fallback 链:
font-family: 'MyFont', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif - 对关键容器(如按钮、导航栏)加
width: min-content或固定min-width,防止文字替换后宽度突变 - 中文字体务必做子集化(剔除不用的汉字),否则体积大、加载慢、fallback 窗口易超时
最容易被忽略的一点:所有字重都得配 font-display,哪怕你只在 CSS 里用了 font-weight: 700,如果 @font-face 声明里没给 bold 版本加 font-display: fallback,那一行字就会 FOIT(白屏)。这不是配置遗漏,是浏览器按规则严格执行。


















