字体格式顺序重要是因为浏览器按src声明顺序匹配,遇到首个可加载格式即停止;应按兼容性从低到高排列:eot→woff2→woff→ttf→otf,确保旧浏览器有兜底。
浏览器对 @font-face 中 src 声明的解析是顺序匹配、遇到第一个能加载的就停,不会继续往后试。如果把 woff2 放最后,旧版 Safari(12 之前)、IE 会跳过它直接尝试下一个,但若下一个是 woff 而你又没提供,就会 fallback 到系统字体。
eot),再逐步升级eot → woff2 → woff → truetype(ttf)→ opentype(otf)woff2,但 iOS Safari 11–12.1 对 woff2 支持不稳定,需保留 woff 作兜底@font-face { font-family: 'MyFont'; src: url('myfont.eot'); /* IE9 */ src: url('myfont.eot?#iefix') format('embedded-opentype'), /* IE6–IE8 */ url('myfont.woff2') format('woff2'), /* Chrome 36+, Firefox 39+, Safari 12.1+ */ url('myfont.woff') format('woff'), /* iOS Safari <12.1, Android WebView */ url('myfont.ttf') format('truetype'); /* fallback for very old Android */}
不是报 404,而是控制台静默无响应,文字直接渲染成默认字体。常见于 Android 4.4–5.1 的系统 WebView,它们声明支持 woff2,但实际解析失败或缓存策略异常。
caniuse 的“支持”标记做判断,得实测真机woff,别强推 woff2
woff2,加个 JS 检测并动态注入:document.fonts.load('1em "MyFont"') 失败后手动切换 src 列表默认值是 font-display: auto,Chrome 和 Firefox 会等字体加载完成才渲染文本(FOIT),用户看到空白或卡顿;Safari 则倾向快速显示系统字体再替换(FOUT),造成明显闪烁。
font-display: swap(立即用系统字体,加载完立刻换)block 适合品牌字体且可接受短时空白;fallback 更平衡,2s 内未加载就用系统字体,之后加载成功也不替换font-display 支持不完整,需配合 JS fallback 检测本地开发用 file:// 协议打开 HTML 时,Chrome 会拒绝加载跨源字体(即使同目录),报错:Access to font at 'file:///xxx.woff2' from origin 'null' has been blocked by CORS policy。
立即学习“前端免费学习笔记(深入)”;
npx serve 或 VS Code Live Server),避免 file:// 直接访问Access-Control-Allow-Origin: *(或具体域名)location ~ .(woff2|woff|eot|ttf|otf)$ {add_header Access-Control-Allow-Origin *;add_header Cache-Control "public, max-age=31536000";}
字体加载的坑多数不在写法本身,而在「你以为它该行,其实某个小版本悄悄改了行为」——比如 iOS Safari 12.2 修复了 woff2 的一个解码 bug,但 12.1 还在出问题;又比如 Android 7.0 的 WebView 把 font-display: swap 当成 auto 处理。上线前至少要在 iOS 11–15、Android 5–12 的真机上跑一遍字体渲染快照。