font-display: swap是字体失败回退的硬性前提,不加则浏览器默认阻塞渲染约3秒,无法触发回退;它强制先用系统字体显示,再替换为加载成功的自定义字体。

不加 font-display: swap,就谈不上“失败回退”——浏览器根本不会给你换字体的机会。
font-display: swap 是回退生效的硬性前提
浏览器默认用 font-display: auto(等同于 block),会卡住文本渲染最多 3 秒,等字体加载完才显示。这时候哪怕字体 404,你也只看到空白或布局跳动,压根没触发“回退”逻辑。
swap 的作用是强制立即用系统字体撑开布局,等网络字体就绪后再替换。所谓“失败回退”,本质是第一个 src 加载失败后,浏览器自动试下一个。
- 必须写在
@font-face规则里,CSS 其他地方设font-display无效 - 只对
src列表中第一个成功解析的字体起作用;如果local("PingFang SC")匹配上了,后续url()根本不发请求 - Safari 14.1+ 才完整支持,旧版 Safari 会降级为
auto,首屏仍可能白屏
@font-face 的 src 顺序决定回退链路
浏览器按 src 声明顺序逐个尝试:本地 → woff2 → woff → ttf → 系统字体栈。中间任何一个成功,就停住;失败才往下走。
常见错误是把 url() 放最前,CDN 一挂,连本地字体都来不及试,用户直接面对 Times New Roman 或空白。
使用 PptxGenJS 和 Python 解析,将结构化的 HTML/CSS 幻灯片内容转换为原生、可编辑的 PowerPoint(.pptx)演示文稿。
- 推荐顺序:
local()→url(...woff2)→url(...woff)→ 不再写url(),靠font-family后续回退到系统字体栈 -
local("Inter")在 Windows/Linux 下静默跳过,不报错也不阻塞,但别指望它跨平台兜底 - 系统字体栈要写全:
"-apple-system", "BlinkMacSystemFont", "Segoe UI", "Roboto", "Helvetica Neue", Arial, sans-serif,少一个可能在某系统上掉进 Courier New
怎么确认字体真被用了,而不是“看起来正常”?
文字显示出来 ≠ 你配的字体生效了。浏览器静默跳过失败项,你根本收不到通知。
打开 DevTools → Network,过滤 woff2,看是否发出请求、返回 200 还是 404/timeout;如果没请求,说明被 local() 截胡,或 CSS 没生效。
- 用
document.fonts.load("1em 'YourFontName'")可检测字体是否可加载,但它不保证渲染时真被选中 - 更可靠的是监听
document.fonts.onloadingerror(Chrome/Firefox),或用fontfaceobserver.check()捕获失败 -
font-weight和font-style不匹配也会导致“隐性失败”:比如页面用font-weight: 600,但@font-face只声明了normal,浏览器就跳过它,转用系统字体
Canvas 上字体加载失败的表现和修复
Canvas 调用 fillText() 或 measureText() 时,如果字体还没就绪,它会静默降级到默认无衬线体,且不会重绘——你看到的“文字突然变宽/偏移”,就是这个原因。
不能靠 window.onload 或 DOMContentLoaded,它们不保证字体已解析完成。
- 必须等
document.fonts.load('bold 16px "PixelFont"')的 Promise resolve 后,再执行首次绘制 - 所有涉及文字宽度计算的逻辑(按钮居中、自动缩放)都得延迟到此时再跑
- 多字重场景(
bold、italic)必须单独声明对应@font-face,否则 Canvas 对合成字体支持极差,容易直接 fallback -
context.font中字体名含空格时,必须用引号包裹:"16px 'Press Start 2P'",否则解析失败
最容易被忽略的点是:字体文件返回 200 并不代表可用——内容损坏、CORS 阻止解析、甚至服务器返回 HTML 错误页,都会让 document.fonts.load() 仍 resolve。真要稳,得结合 document.fonts.status 和实际渲染结果校验。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!










