HTML如何做字体加载优化_html字体加载性能优化方案【零基础】

作者:袖梨 2026-07-27
必须显式设置font-display(推荐swap)、preload字体时加crossorigin、只用WOFF2格式、用document.fonts.load()主动检测加载状态,否则字体加载失败无法感知。

字体加载不优化,首屏文字就可能白屏3秒——这不是 bug,是浏览器默认行为。必须用 font-display 控制,再配合 preload 和 WOFF2,否则用户看到的就是 FOIT(文字消失)或 FOUT(文字跳动)。

font-display 必须显式设置,别信 auto

浏览器对 @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>}

preload 字体必须带 crossorigin,否则无效

<link rel="preload"> 是唯一能提前触发字体下载的 HTML 级手段,但漏掉 crossorigin 属性,浏览器会直接忽略该 preload 请求——哪怕字体同源。

立即学习“前端免费学习笔记(深入)”;

  • 必须同时写 as="font"type="font/woff2"crossorigin
  • 只对当前导航中「确定马上要用」的字体做 preload,比如首屏标题/正文所用字体
  • preload 不替代 @font-face,两者要共存:preload 负责提前取,@font-face 负责声明和应用
  • 在 Chrome DevTools Network 面板里,正确 preload 的请求 Priority 显示为 high,否则就是写错了

正确写法:

<link rel="preload" href="/fonts/Inter.woff2" as="font" type="font/woff2" crossorigin>

只上线 WOFF2,别打包 TTF/EOT/woff1

WOFF2 在所有现代浏览器(Chrome 36+、Firefox 39+、Safari 10+、Edge 14+)已原生支持,且体积比 TTF 小 30%~80%(中文字体子集化后更明显)。继续提供其他格式只会增加 CDN 缓存压力、HTTP 请求数和构建复杂度。

  • 构建流程中用 fonttoolsweb-font-generator 直接转 WOFF2,删掉所有其他格式
  • 检查服务器响应头:.woff2 文件必须返回 Content-Type: font/woff2,否则部分浏览器拒收
  • IE11 已退出主流支持周期,不建议为它保留 EOT 或 TTF——真有强制需求,单独走条件注释或 JS 动态加载
  • 字体路径错误、CORS 拦截、404 这些问题,font-display: swap 压根不会报错,你得靠 JS 主动检测

document.fonts.load() 是唯一能确认字体是否加载成功的手段

font-display 只控制渲染策略,不提供加载状态反馈。CDN 故障、路径拼错、跨域拒绝这些情况,用户永远看到的是 fallback 字体,而你完全不知情。

  • document.fonts.load("12px 'Inter'") 主动检测,返回 Promise
  • 成功时可加 class 触发动画、上报埋点;失败时可降级提示或切回系统字体栈
  • 注意:该 API 在 Safari 10+、Chrome 35+、Firefox 41+ 支持,旧版需 feature detect 后降级
  • 不要只测一次——字体加载失败后,document.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 检测必须跟上,否则优化只是自我安慰。

相关文章

精彩推荐