必须显式设置font-display(推荐swap)、preload字体时加crossorigin、只用WOFF2格式、用document.fonts.load()主动检测加载状态,否则字体加载失败无法感知。
字体加载不优化,首屏文字就可能白屏3秒——这不是 bug,是浏览器默认行为。必须用 font-display 控制,再配合 preload 和 WOFF2,否则用户看到的就是 FOIT(文字消失)或 FOUT(文字跳动)。
浏览器对 @font-face 的默认行为是 font-display: auto,实际等同于 block:先藏文字约 100ms,再等字体加载最多 3 秒,失败才 fallback。这对内容型页面就是灾难。
swap:最常用,立即显示备用字体,加载完立刻替换(注意可能重排)fallback:给自定义字体约 100ms 加载窗口,超时就永久用备用字体,适合非品牌关键文本optional:只在缓存命中或网络极快时才用,适合装饰性标题字,避免无谓请求block,它等于主动制造 FOIT;也别省略 font-display,等于默认启用 block
示例写法:
@font-face {<br> font-family: "Inter";<br> src: url("/fonts/Inter.woff2") format("woff2");<br> font-display: swap;<br>}
<link rel="preload"> 是唯一能提前触发字体下载的 HTML 级手段,但漏掉 crossorigin 属性,浏览器会直接忽略该 preload 请求——哪怕字体同源。
立即学习“前端免费学习笔记(深入)”;
as="font"、type="font/woff2" 和 crossorigin
@font-face,两者要共存:preload 负责提前取,@font-face 负责声明和应用high,否则就是写错了正确写法:
<link rel="preload" href="/fonts/Inter.woff2" as="font" type="font/woff2" crossorigin>
WOFF2 在所有现代浏览器(Chrome 36+、Firefox 39+、Safari 10+、Edge 14+)已原生支持,且体积比 TTF 小 30%~80%(中文字体子集化后更明显)。继续提供其他格式只会增加 CDN 缓存压力、HTTP 请求数和构建复杂度。
fonttools 或 web-font-generator 直接转 WOFF2,删掉所有其他格式Content-Type: font/woff2,否则部分浏览器拒收font-display: swap 压根不会报错,你得靠 JS 主动检测font-display 只控制渲染策略,不提供加载状态反馈。CDN 故障、路径拼错、跨域拒绝这些情况,用户永远看到的是 fallback 字体,而你完全不知情。
document.fonts.load("12px 'Inter'") 主动检测,返回 Promisedocument.fonts.load() 仍会 resolve,需结合 document.fonts.check() 判断是否真可用简单检测示例:
document.fonts.load("16px 'Inter'").then(() => {<br> if (document.fonts.check("16px 'Inter'")) {<br> document.body.classList.add("fonts-loaded");<br> }<br>}).catch(() => console.warn("Inter font failed to load"));
真正卡住人的不是怎么写,而是字体加载失败时没人知道——font-display 让页面看起来“正常”,却掩盖了资源链路的真实断裂点。监控和 fallback 检测必须跟上,否则优化只是自我安慰。