CSS的@font-face规则允许网页加载自定义字体,突破系统字体限制,实现跨平台视觉一致性。
其核心语法包含font-family(自定义字体名)、src(字体文件路径)、font-weight(字重)等属性,支持WOFF2/WOFF等格式。
配合font-display:swap策略可优化性能,确保文字内容即时显示,避免加载延迟。
实际应用中需注意字体子集化、按需加载等技巧,平衡设计自由度和网页性能。
该技术是现代网页实现品牌字体、多语言支持的关键方案,同时需兼顾SEO和用户体验指标。
@font-face
@font-face 是 CSS 中的一个规则(at-rule),它允许网页使用服务器上的自定义字体文件,而不必依赖用户操作系统中预装的字体。
简单来说,它让设计师可以在网页上使用任何想要的字体(包括付费商业字体、公司品牌字体、或免费开源字体),只要用户能下载到字体文件,就能正常显示。
1. 为什么需要 @font-face?
在没有 @font-face 之前,网页只能用用户电脑上已安装的字体,比如:
-
Windows:Arial、微软雅黑、宋体
-
macOS:Helvetica、PingFang
这导致跨平台、跨设备时,网页视觉效果差异很大。@font-face 的出现解决了这个问题。
2. 基本语法
css
@font-face {
font-family: 'MyCustomFont'; /* 自定义字体名称,后面引用时用这个 */
src: url('fonts/myfont.woff2') format('woff2'), /* 字体文件路径 */
url('fonts/myfont.woff') format('woff'); /* 降级方案 */
font-weight: normal; /* 字重 */
font-style: normal; /* 样式 */
font-display: swap; /* 加载策略 */
}
定义之后,就可以像普通字体一样使用了:
css
body {
font-family: 'MyCustomFont', 'Arial', sans-serif;
}
3. 各个属性的作用
| 属性 | 作用 | 示例 |
|---|---|---|
font-family |
给这个自定义字体起一个名字,供后续 CSS 引用 | 'MyFont'、'PingFang SC' |
src |
指定字体文件的路径和格式。可以写多个,浏览器会按顺序选择支持的格式 | url('font.woff2') format('woff2') |
font-weight |
定义这个字体文件对应的是哪个字重(普通、粗体等) | normal、bold、400、700 |
font-style |
定义这个字体文件对应的是正常还是斜体 | normal、italic |
font-display |
控制字体加载期间的渲染行为 | swap、block、fallback、optional |
unicode-range |
指定该字体只用于哪些 Unicode 字符(常用于按语言或符号拆分字体) | U+4E00-9FFF(仅中文) |
4. 实际应用场景
场景 1:使用 Google Fonts 等第三方字体
实际上 Google Fonts 底层就是生成 @font-face 规则:
css
/* 从 Google Fonts 加载 Noto Sans */
@import url('https://fonts.googleapis.com/css2?family=Noto+Sans:wght@400;700&display=swap');
它内部展开后类似:
css
@font-face {
font-family: 'Noto Sans';
src: url(https://fonts.gstatic.com/.../NotoSans-Regular.woff2) format('woff2');
font-weight: 400;
font-display: swap;
}
场景 2:加载本地字体文件(自托管)
很多公司为了性能或隐私考虑,会把字体文件放在自己的服务器上:
css
@font-face {
font-family: 'BrandFont';
src: url('/fonts/brand-regular.woff2') format('woff2');
font-weight: 400;
font-display: swap;
}
@font-face {
font-family: 'BrandFont';
src: url('/fonts/brand-bold.woff2') format('woff2');
font-weight: 700;
font-display: swap;
}
场景 3:按需加载不同语言的字体(优化性能)
css
@font-face {
font-family: 'MyFont';
src: url('latin.woff2') format('woff2');
unicode-range: U+0000-00FF; /* 只加载拉丁字母 */
}
@font-face {
font-family: 'MyFont';
src: url('chinese.woff2') format('woff2');
unicode-range: U+4E00-9FFF; /* 只加载中文 */
}
这样用户访问英文页面时,只下载英文字体,不下载中文字体,节省流量。
5. 常见的字体格式
| 格式 | 特点 | 浏览器支持 |
|---|---|---|
| WOFF2 | 压缩率最高,体积最小,首选格式 | 现代浏览器全面支持 |
| WOFF | 兼容性比 WOFF2 稍好 | IE9+、所有现代浏览器 |
| TTF / OTF | 体积较大,未经压缩 | 老浏览器兜底用 |
| EOT | 微软专属格式 | 仅 IE(已基本淘汰) |
| SVG | 体积大,渲染慢 | iOS 早期版本(已淘汰) |
推荐写法:WOFF2 优先,WOFF 兜底。
css
src: url('font.woff2') format('woff2'),
url('font.woff') format('woff');
6. @font-face 与性能
使用 @font-face 会带来额外的网络请求和下载开销,需要注意:
-
体积控制 :中文/日文等 CJK 字体动辄几 MB,建议使用字体子集化(只保留页面用到的字符)
-
加载策略 :配合
font-display: swap避免文字不可见 -
预加载 :关键字体使用
<link rel="preload">提前加载 -
只加载需要的字重 :不要一次性加载
400、500、600、700四个文件,按需加载
7. 总结
| 问题 | 答案 |
|---|---|
@font-face 是什么? |
CSS 规则,用于在网页中加载和使用自定义字体文件 |
| 核心作用 | 打破"只能用系统字体"的限制,实现跨平台视觉一致性 |
| 常用属性 | font-family、src、font-weight、font-display |
| 性能要点 | 使用 WOFF2 格式、配合 swap、做字体子集化、按需加载 |
@font-face + font-display: swap 是现代 Web 字体加载的标准搭配,既保证了设计自由度,又兼顾了用户体验和性能。
font-display: swap;
是 CSS 中 @font-face 规则的一个属性,它控制自定义字体 的加载行为,对网页性能(尤其是 LCP 最大内容绘制)和用户体验有显著影响。
简单来说,它的核心逻辑是:
先让文字立即用系统默认字体显示,等自定义字体下载完成后,再"无感"地替换掉。
1. 它是如何工作的?
使用 swap 时,浏览器的渲染流程如下:
-
立即渲染(FOUT) :浏览器检测到文字需要显示,但自定义字体还没下载完。此时不会等待,直接使用备用的系统字体(如 Arial、Helvetica)渲染出文字。
-
替换:几毫秒或几秒后,自定义字体下载完成。
-
重绘:浏览器将已经显示的文字"换装",替换为自定义字体。
2. 为什么要用 swap?
在没有设置 font-display 或设置错误时,浏览器默认会有 FOIT(Flash of Invisible Text,不可见文本闪烁)。
即浏览器在下载字体时(通常最多 3 秒),会让文字完全消失(透明)。
如果网络慢,用户会看到几秒钟的白屏或空白区域,然后文字才突然出现。
使用 swap 后,用户会立即看到文字 ,虽然一开始不是设计师想要的艺术字体,但至少保证了内容的可读性,解决了"文字延迟出现"的糟糕体验。
3. 代码示例
css
@font-face {
font-family: 'MyCustomFont';
src: url('myfont.woff2') format('woff2');
font-display: swap; /* 关键设置 */
}
body {
font-family: 'MyCustomFont', 'Arial', sans-serif;
}
4. font-display 的其他选项对比
为了帮助你理解为什么 swap 是最常用的策略,这里列出其他几个选项:
| 值 | 行为 | 适用场景 |
|---|---|---|
swap |
立即显示备用字体,加载完成后替换。 | 绝大多数场景。兼顾了阅读体验和最终视觉效果。 |
block |
先隐藏文字(最多3秒),如果3秒内没加载完,才显示备用字体。 | 很少用。会导致文字延迟出现,影响 LCP。 |
fallback |
极短时间隐藏(约100ms),如果还没加载完,则使用备用字体。如果备用字体已显示,之后不再替换。 | 性能优先。防止网络慢时出现"闪烁式替换"。 |
optional |
极短时间检查字体是否在缓存中。如果不在,则永远使用系统字体,且浏览器可以随时取消下载以节省流量。 | 极度性能敏感,或非品牌强相关的字体。 |
5. 对 SEO 和 Core Web Vitals 的影响
在 Google 的 Core Web Vitals(核心网页指标)中,LCP(最大内容绘制) 是非常关键的评分项。
-
如果没有
font-display: swap:如果最大内容的元素是文字(通常是标题),浏览器会等待字体下载,导致 LCP 时间延长,影响搜索排名和用户体验。 -
如果使用
swap:最大内容元素会立即被绘制(使用备用字体),LCP 时间通常较短,有利于 SEO。
6. 需要注意的副作用:FOUT
使用 swap 最大的缺点是 FOUT(Flash of Unstyled Text,样式未生效文本闪烁)。用户会先看到系统字体的文字,过一会突然"跳"成自定义字体。
缓解策略:
-
使用
preload(预加载) :对于首屏最重要的字体(如标题字体),使用<link rel="preload" href="myfont.woff2" as="font" crossorigin>提前加载,缩小"先显示 Arial,后显示自定义"的时间差。 -
调整后备字体 :选择与自定义字体在宽度、高度上接近的系统字体(如
system-ui),减少字体切换时的布局偏移(CLS,累计布局偏移)。
总结 :font-display: swap 是 Web 性能优化的最佳实践,它牺牲了"视觉一致性"的短暂时间,换取了"内容可读性"的绝对稳定,是目前解决自定义字体加载问题最主流的方案。