自定义字体不生效主因是@font-face未加载或字体名不一致:须确保@font-face中font-family与调用处完全一致(含引号、大小写、空格),路径可访问,且声明font-display: swap并验证network面板200响应。

自定义字体不生效,90% 是 @font-face 没真正加载进浏览器,或 $font-family-sans-serif 变量改了但没同步到实际字体文件声明里。
为什么改了 $font-family-sans-serif 还是显示系统字体
变量只是“起个名字”,不代表字体存在。比如只在 _custom.scss 里写:
$font-family-sans-serif: 'MyLocalFont', sans-serif;
而没做下面两件事,浏览器根本找不到 'MyLocalFont':
- 在 CSS 中用
@font-face声明该字体,且font-family值必须和变量里完全一致(包括引号、空格、大小写) - 确保字体文件路径在构建后可访问——Webpack/Vite 下
url('../fonts/MyLocalFont.woff2')容易因入口文件层级不同变成 404 - HTML 的
中没预加载,首屏文字大概率闪一下再变样,甚至触发 CLS
如何正确写 @font-face 并避免 FOIT 和布局偏移
不加 font-display: swap,Chrome/Firefox 下极易出现空白文本(FOIT)或回退字体突然跳变(CLS),影响 Core Web Vitals。必须显式声明:
@font-face {
font-family: 'MyLocalFont';
src: url('../fonts/MyLocalFont.woff2') format('woff2');
font-display: swap;
}
-
font-display: swap是关键:立即用 sans-serif 渲染,等本地字体加载完再无感替换 - 别用
auto(默认值)或block,尤其在移动端首屏文字上 - 如果字体有多个字重(如 400、700),每个都要单独写一个
@font-face块,font-weight不能省
怎么验证字体是否真被浏览器用了
别只看变量或 CSS 文件里有没有声明,要查运行时真实行为:
- 打开 DevTools → Elements → 选一个
<h1></h1>或<p></p>元素 → Computed → 找font-family,看是否列出'MyLocalFont'(注意引号) - 搜索最终生成的
app.css,Ctrl+F 查@font-face和你的字体名,确认规则存在且src路径可点击下载 - 禁用网络后刷新页面:如果文字立刻变成方块或全退回
sans-serif,说明字体没内联、也没预加载成功 - 检查 Network 面板里字体请求是否返回 200;404 就是路径错,failed 可能是跨域或 MIME 类型缺失(尤其 IIS)
构建工具下常见路径失效点
Vite/Webpack 不会自动修正 CSS 中的 url() 相对路径,尤其当 SCSS 入口和字体目录不在同一级时:
- 假设
src/scss/main.scss引入了_custom.scss,而字体放在src/assets/fonts/,那么url('../assets/fonts/...')才对,不是url('../fonts/...') - 推荐统一用绝对路径:
url('/fonts/MyLocalFont.woff2'),并确保构建后该路径真实存在(比如部署到 Nginx 的/fonts/目录) - Vite 用户检查
vite.config.ts是否启用了css.preprocessorOptions.sass.additionalData,它可能干扰@import顺序
最常被忽略的是:改了 Sass 变量却忘了把 @font-face 块 import 进主样式入口,或者构建缓存没清,导致旧 CSS 一直生效。每次改完,务必清缓存、重新 build、再查 Network 和 Computed。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











