必须显式写 font-display: swap,否则浏览器按 auto(等同 block)策略隐藏文本100ms并最多等待3秒,导致foit白屏;swap是唯一不改html/js让文本立刻可见的方案。

不优化 font-display,系统字体就不是“系统字体”——浏览器会把它当成 Web 字体一样藏起来等加载,首屏白屏 1–3 秒是默认行为,不是网络问题。
为什么必须显式写 font-display: swap
浏览器对 @font-face 的默认策略是 font-display: auto,实际等同于 block:文本先隐藏约 100ms,再最多等待 3 秒加载字体,失败才 fallback。你看到的“空白段落”,不是加载慢,是浏览器在严格执行规范。
- 没写
font-display→ 等同于block→ FOIT(文字消失)必然发生 - 写了但值是
block→ 主动延长不可见时间,毫无必要 -
swap是唯一能在不改 HTML、不写 JS 的前提下,让文本「立刻可见」的方案 - 替换时可能轻微重排(尤其字宽差异大),但比白屏好十倍
preload 字体必须带 crossorigin 才生效
<link rel="preload"> 是唯一能在 HTML 解析阶段就触发字体下载的手段,但漏掉 crossorigin,浏览器会静默忽略该请求——哪怕字体跟页面同源。
- 必须同时满足三项:
as="font"+type="font/woff2"+crossorigin(值为空即可,crossorigin=""或crossorigin都行) - 没写
crossorigin→ Network 面板里看不到请求,或 Priority 显示为lowest - 写了
crossorigin但服务端没配 CORS 响应头 → 控制台报CORS error,字体加载失败 - 只对首屏确定用到的字重做 preload,比如
Inter-Bold.woff2,别把整套 variable font 全 preloaded
只上线 .woff2 格式,并做子集化
所有现代浏览器(Chrome 36+、Firefox 39+、Safari 10+、Edge 14+)原生支持 .woff2,压缩率比 .ttf 高 30%~80%,中文字体子集化后效果更明显——常用汉字 + ASCII 子集常压到原体积 20% 以内。
- 必须提供至少两个格式 fallback:优先
url("font.woff2") format("woff2"),降级到url("font.woff") format("woff");不要用.ttf,它没压缩、体积大 - 删掉
.eot、.svg、.otf—— IE11 已退出主流支持周期,保留它们只会拖慢所有现代用户 - 服务器响应头必须返回
Content-Type: font/woff2,否则部分浏览器拒收 - 构建时用
pyftsubset(fonttools)或 Transfonter 生成子集,不是靠 JS 动态判断
@font-face 中 format() 和 fallback 字体链不能省
写了 font-display: swap 却没效果?大概率是被浏览器忽略了。常见原因:
-
src没声明format("woff2"),旧版 Safari/Edge 会跳过该条目,退回到默认block行为 - fallback 字体链混用衬线与无衬线(如
"Georgia", "Inter"),字宽差超 20%,导致重排明显 - 中文字体 fallback 没分平台写清楚,比如只写
sans-serif,没列"PingFang SC", "Hiragino Sans GB", "Microsoft YaHei" - 用了
@import引入字体 CSS → 预加载失效,也延迟解析时机
真正容易被忽略的点是:字体加载失败时,swap 会让内容始终可读,但你完全感知不到失败本身——document.fonts.load() 只适合上报,不能控制首屏;而 fallback 字体选得不准,重排就会比白屏更伤体验。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











