@font-face在IE9和旧版Android中不生效,主因是字体格式兼容性与src顺序错误:IE9仅支持嵌入式.eot,旧版Android仅支持.ttf,且IE9遇不识别格式会跳过整条规则;应按.eot、.eot?#iefix、.woff2、.woff、.ttf倒序声明,并确保.eot含embed标志。

为什么@font-face在IE9或旧版Android浏览器里不生效
核心问题不是写法错,而是字体格式和src声明顺序不兼容。IE9只认.eot(且必须是“embedded”类型),旧版Android WebKit只支持.ttf,而现代浏览器优先用.woff2。如果把.woff2写在最前面,IE9会直接跳过整个@font-face规则(不识别该格式,且不降级尝试后续源)。
实操建议:
- 按浏览器兼容性倒序排列
src:先写url('font.eot'),再url('font.eot?#iefix')(触发IE私有解析),接着url('font.woff2')、url('font.woff')、url('font.ttf') -
.eot文件必须用fontforge或transfonter.org生成带embed标志的版本,普通导出的.eot在IE9中常被拒绝加载 - 避免在
src里混用format('woff2')和format('woff')以外的类型说明——旧版Safari对format('truetype')识别不稳定,直接省略更安全
Chrome/Firefox字体闪烁(FOIT)比预期更久怎么压
默认情况下,浏览器对@font-face字体有3秒超时策略:若字体未加载完成,就先用后备字体渲染,等加载完再重绘(造成可见闪烁)。这个行为不可关闭,但可缩短感知延迟。
实操建议:
- 加
font-display: swap——这是最直接有效的解法,让浏览器立即用后备字体,加载完立刻替换,用户几乎无感 - 避免同时声明多个
@font-face变体(如Regular、Medium、Semibold)却不预加载;未预加载的变体会各自触发独立超时,拉长整体FOIT窗口 - 不要依赖
local()声明试图复用系统字体——不同系统同名字体字形差异大,且local('PingFang SC')在非macOS设备上会跳过,反而增加网络请求次数
Webpack/Vite项目里@font-face路径失效或404
根本原因是构建工具把字体文件当静态资源处理,但@font-face中的url()路径没随打包逻辑更新。比如开发时写url('./fonts/icon.woff2'),构建后字体被哈希重命名并移到/assets/下,而CSS里的路径没变。
实操建议:
- Vite项目:确保
public/目录放字体,并在@font-face中用绝对路径url('/fonts/icon.woff2');不要放src/下,否则需配assetsInclude - Webpack项目:用
file-loader或asset/inline处理.woff2等扩展名,并在css-loader中开启url: true(默认已开),让url()被自动重写 - 检查浏览器Network面板里字体请求的
Referrer头——如果是about:blank,大概率是CSS被内联进HTML但字体路径写成相对路径导致解析失败
字体加载完成但文字没重绘(尤其iOS Safari)
这不是缓存问题,而是iOS Safari对font-display: swap的实现缺陷:当字体加载完成,它不会主动触发重排,除非DOM发生变动或窗口被resize。用户会看到文字一直卡在后备字体上。
实操建议:
- 监听
document.fonts.load()成功后,强制触发布局抖动:getComputedStyle(document.body).transform(读取任意触发重排的属性即可) - 避免在
font-face中使用unicode-range切分过细(如单个汉字范围),iOS Safari对动态unicode-range的匹配和重绘支持极差 - 不要用
font-weight: 500去匹配实际只有400和700两个文件的字体族——Safari会拒绝映射,也不报错,静默回退到系统字体
真正麻烦的从来不是写几行@font-face,而是每个浏览器对“加载完成”的定义不同,对“该不该重绘”的判断逻辑也藏在底层渲染管线里。多测真机,少信CanIUse的绿色对勾。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











