font-display: optional 是浏览器在100ms内无法就绪时直接放弃加载自定义字体、全程使用后备字体的策略,彻底避免FOIT和FOUT;它适用于非关键文字,但需为每个字重单独声明@font-face并配合preload与排版锁定。

font-display: optional 是什么,它真能避免闪烁?
font-display: optional 不是“让字体不闪”,而是让浏览器**跳过加载**——当网络慢、缓存未命中、或预估加载时间 > 100ms 时,浏览器直接放弃请求该字体,全程使用 font-family 回退链里的系统字体。没有加载,自然没有替换,也就没有 FOUT(文字跳变)或 FOIT(文字空白)。但它不是万能开关:它只对「非关键文字」有效,比如装饰性标题、icon font、次要 banner 文字。
这个值的底层逻辑是:宁可不用你的字体,也不让用户等、不触发重排、不增加渲染压力。
为什么设了 optional 还在弱网下看到字体变细/模糊?
常见错误现象:font-weight: 600 文字突然变回 400、边缘发虚、甚至降级到 serif ——这不是 optional 失效,而是你漏写了对应字重的 @font-face 声明。
浏览器在 optional 模式下不会合成字重,也不会 fallback 到同族其他声明;它只找「完全匹配」的 @font-face:font-family + font-weight + font-style 必须全部一致。
- 每个要用的
font-weight(如 400、500、600、700)都得有独立的@font-face块,且都显式写上font-display: optional - 别指望一个
src文件支持所有字重;WOFF2 子集化时也要按字重拆分 - 如果只声明了
font-weight: 400,但 HTML 里写了font-weight: 600,浏览器会直接跳过整个自定义字体,用系统默认加粗(可能失真)
怎么配合 preload 让 optional 更靠谱?
optional 和 preload 看似矛盾,实则互补:preload 提前触发 DNS + TCP + 字体文件下载,让浏览器在判断“是否值得加载”时有更准的依据(比如缓存已命中,就大概率启用)。
但必须满足三个硬条件,否则 preload 会被忽略或引发 CORS 错误:
-
<link rel="preload">的href必须和@font-face src中的路径**完全一致**(含查询参数,如?v=2) - 必须带
crossorigin属性,哪怕字体同源——WOFF2 加载强制跨域模式 - 只预加载 WOFF2 格式;别加 WOFF/TTF,浏览器不会复用
<link rel="preload" href="/fonts/inter-bold-latin.woff2?v=2" as="font" type="font/woff2" crossorigin>
移动端用 optional 要特别注意什么?
iOS Safari 和部分 Android Chrome 版本对 optional 的实现更激进:即使缓存存在,只要页面首次访问、或 LCP 元素尚未稳定,也可能直接跳过加载。这不是 bug,是策略性降级。
所以不能只靠 optional 就交差,还得做两件事:
- 给文字容器显式设置
font-size、line-height、height,防止系统字体和 Web 字体度量差异导致布局抖动 - 首屏关键文案(如 logo、主标题)不要用
optional;改用fallback或swap+ 子集化 + preload - 中文字体慎用
optional——单个子集仍可能超 300KB,弱网下 100ms 内几乎不可能就绪
真正容易被忽略的点在于:optional 不是“设了就完事”的属性,它是整套字体交付链路的终点判断。从 @font-face 声明粒度、preload 路径一致性,到移动端排版锁定,缺一不可。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











