font-display: swap 是目前唯一被主流浏览器支持的 css 缓解 fout 的手段,它立即用系统字体渲染,待 web 字体加载完再替换,但替换仍会重绘;需配合 format() 声明、woff2 优先、preload 及 ios 兜底方案。

font-display: swap 能缓解 FOUT,但不能彻底消除
字体加载闪烁(FOUT / FOIT)本质是浏览器在 Web 字体就绪前的渲染策略问题,font-display 是目前唯一由 CSS 控制、且被主流浏览器支持的缓解手段。它不改变字体是否加载,只决定「何时用后备字体、何时切到自定义字体」。
常见取值中只有 swap 明确承诺:立即用系统字体渲染文本,等 Web 字体加载完成后再无感替换——这是最贴近“解决闪烁”预期的行为。但注意:替换本身仍是一次重绘,肉眼可能捕捉到轻微跳动,尤其在长段落或字号变化大的场景。
-
font-display: block会阻塞文本渲染长达 3s(各浏览器略有差异),造成空白(FOIT),比闪烁更伤体验 -
font-display: fallback限制渲染等待时间很短(约 100ms),适合图标字体等非关键文本 - 不声明
font-display时,Chrome 默认行为接近block,Safari 早期版本甚至不支持该属性
必须配合 @font-face src 中的 format() 声明才生效
font-display 只在 @font-face 规则里起作用,且仅当 src 正确标注字体格式时,浏览器才能准确预估加载行为。漏写 format() 或写错(比如把 .woff2 写成 format("woff"))会导致部分浏览器降级处理,font-display 可能被忽略。
正确写法示例:
@font-face {
font-family: "MyFont";
src: url("myfont.woff2") format("woff2"),
url("myfont.woff") format("woff");
font-display: swap;
}
- 优先放
woff2,并明确标注format("woff2");否则旧版 Edge 可能跳过该条目 - 不要混用
local()和远程字体却不加format(),本地匹配失败后 fallback 行为不可控 - 使用
preload提前获取字体文件可进一步缩短 swap 窗口,但需搭配as="font"和type="font/woff2"
font-display: swap 在 iOS Safari 上有兼容性陷阱
iOS 14.5 之前,Safari 对 font-display: swap 支持不完整:即使字体已加载完成,也不会触发替换,导致页面始终显示后备字体。这个问题在 iOS 14.5+ 已修复,但若需支持更老版本,得靠 JavaScript 补救。
- 检测方式:用
document.fonts.check("1em MyFont")判断是否加载成功,再手动触发重排(如修改body的font-family临时值) - 更稳妥的做法是放弃纯 CSS 方案,改用
FontFaceAPI +load()显式控制加载时机 - 注意:iOS Safari 对
FontFace的unicodeRange支持有限,分段加载时别依赖它做精细切割
字体文件体积和 CDN 缓存直接影响 swap 效果
再正确的 font-display 配置,也救不了一个 2MB 的未压缩 .ttf。swap 的“无感”前提是字体加载足够快——通常应控制在 1s 内完成下载(3G 网络下)。否则用户看到的是:先系统字体 → 等待 → 突然整块文字跳变,比不 swap 还突兀。
- 优先用
.woff2格式,比.woff平均小 30%;禁用未启用的字重/字宽,避免全量加载 - 确保 CDN 返回
Cache-Control: public, max-age=31536000,字体文件应长期缓存 - 避免在
@font-face中使用通配符url(*.woff2),Webpack/Vite 等构建工具需显式导出字体资源路径,否则 404 会让 swap 永远不发生
font-display: swap 就只剩个空壳。前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











