网页字体实战
中文网页字体从加载原理到上线:拆子集、按字分片、写对 @font-face、加载策略、减少跳动、字体栈、自托管许可、排查和新技术。
- 浏览器怎么加载网页字体
- 动手拆子集:pyftsubset
- 按字分片:cn-font-split
- 写对 @font-face:字体名、字重和 local()
- 加载策略:font-display、预连接和预加载
- 减少跳动:后备字体和尺寸调整
- 中文字体栈怎么写
- 用文风网页字体:一页看懂正确接法
- 自托管网页字体的许可要点
- 字体没生效?一套排查顺序
- 可变字体和增量字体传输
浏览器怎么加载网页字体
适合谁看:想搞清楚网页字体从请求到显示经历了什么、为什么会「白屏」或「跳一下」的前端开发者。
@font-face 的基本写法见《在网页里使用字体:@font-face 的现代写法》。本页讲背后的过程,后面几页的优化都从这里出发。
一次加载的顺序
- 下载 HTML,发现 CSS。 字体 CSS 写在
<link>里会较早开始下载;写在@import里要等外层 CSS 下载完才开始。 - 解析 CSS,登记
@font-face。 这一步只是登记「有这么一个字体、文件在哪里」,不会下载字体文件。 - 排版时发现要用它。 页面上某段文字的
font-family用到了这个字体,并且文字里的字符落在它的unicode-range里,浏览器才开始下载对应的文件。 - 等待期间先用别的字体。 字体没到时,按
font-display的规则,要么先不显示文字,要么先用备用字体显示。 - 字体到了,重新排版。 换成新字体后,字宽、行高不同,段落会重新折行,这就是「跳一下」。
所以字体文件开始下载的时间,比 HTML、CSS 都晚,常常排在关键请求的最后面。
「白屏」和「跳一下」
| 现象 | 常见叫法 | 原因 |
|---|---|---|
| 文字区域空白一段时间 | FOIT(隐形文字闪烁) | 浏览器在等字体,期间文字不画出来 |
| 先显示系统字体,然后换掉 | FOUT(无样式文字闪烁) | 先用备用字体,字体到了再替换 |
CSS 规范对 font-display 的建议是:block 最多等约 3 秒;swap、fallback、optional 只等很短的时间(建议不超过 100 毫秒)就先显示备用字体。中文页面字体大,block 会让读者盯着空白很久,所以一般用 swap,见《加载策略:font-display、预连接和预加载》。
跨域字体要允许跨域
字体文件放在另一个域名时,服务器必须返回 Access-Control-Allow-Origin 响应头,否则浏览器会拒绝使用。自己部署字体时要记得配置。
中文为什么特别
一款中文字体通常有几万个字形,单个文件常有几 MB 到十几 MB。直接引用整个文件,字体要很久才能显示。解决办法就是把它拆成很多小文件,每个文件用 unicode-range 标明包含哪些字,浏览器只下载用到的那几片。原理见《中文网页字体为什么要拆分子集》,动手做见《动手拆子集:pyftsubset》 和《按字分片:cn-font-split》。
动手拆子集:pyftsubset
适合谁看:想把一款字体裁成只含页面用到的字、转成 WOFF2 自己部署的开发者。
先确认许可允许修改和网页使用,见《自托管网页字体的许可要点》。
准备
pyftsubset 是 fontTools 自带的子集工具。要输出 WOFF2,还需要 brotli:
pip install fonttools brotli
最常用的三种用法
按一段文字裁: 适合标题、Logo 文字、活动页。
pyftsubset SourceHanSerifSC-Bold.otf \
--text="春日限定 立即报名" \
--flavor=woff2 \
--output-file=title.woff2
按文字文件裁: 把页面上所有文字导出到一个文本文件。
pyftsubset font.ttf --text-file=chars.txt --flavor=woff2 --output-file=page.woff2
按码位范围裁: 例如只留基本拉丁字母和中日韩统一表意文字基本区。
pyftsubset font.ttf --unicodes="U+0020-007E,U+4E00-9FFF" --flavor=woff2 --output-file=cjk-basic.woff2
别把许可信息裁掉
pyftsubset 默认只保留字体名称表里编号 0 到 6 的记录,并且只保留英文的记录。许可说明(编号 13)和许可网址(编号 14)默认会被删掉,中文字体名也会被删掉。自己部署开源字体时,建议加上:
--name-IDs='*' --name-languages='*'
这样字体文件里仍然带着版权和许可信息。
排版功能
pyftsubset 默认保留一批常用的 OpenType 功能,包括竖排相关的 vert、vrt2 和标点挤压相关的 halt、vhal、palt、vpal、chws、vchw 等。要指定保留哪些功能,用 --layout-features;要保留全部,用 --layout-features='*'。
注意事项
- 按页面文字裁,内容一变就缺字。 有用户输入、评论、搜索的地方,不要用固定子集,用分片方案(见下一页)。
- 记得标点和数字。 中文标点、全角空格、数字、常用符号都要包含在内。
- 改名。 开源字体有「保留字体名」时,裁过的字体按许可算修改版,
font-family和文件里的名字最好换掉,见《SIL 开放字体许可证(OFL)逐条读》。
按字分片:cn-font-split
适合谁看:内容不固定(博客、社区、电商),想把整款中文字体拆成很多小片、按需加载的开发者。
分片和子集的区别
- 子集:只留下一部分字,其他字不要了。
- 分片:一个字也不丢,把整款字体切成很多片,每片几十 KB,用
unicode-range标明范围。页面用到哪些字,浏览器就只下载那几片。
文风网页字体用的就是分片,见《性能:子集、字体显示策略和预连接》。自己部署时,可以用开源工具 cn-font-split 生成同样的结构。
cn-font-split 简介
cn-font-split 是「中文网字计划」使用的分片工具,Apache-2.0 许可。它会:
- 按字符使用频率和字体内容分组,生成一批 WOFF2 分片;
- 生成一份 CSS,里面是多条
@font-face,每条带unicode-range; - 可选生成预览图和测试页面。
用法示例(Node.js)
npm install cn-font-split
import fs from 'fs';
import { fontSplit } from 'cn-font-split';
const input = new Uint8Array(fs.readFileSync('./LXGWWenKai-Regular.ttf').buffer);
await fontSplit({
input,
outDir: './dist/font',
css: { fontFamily: 'My WenKai', fontWeight: '400' },
});
参数以官方文档为准,版本更新时可能变化。它还提供命令行、在线切割页面和前端构建插件。
分片后怎么用
- 把输出目录整个放到网站上(或对象存储),保证跨域头和缓存头正确;
- 在页面里引入生成的 CSS;
- 在样式里写 CSS 里声明的
font-family名字和备用字体。
多个字重要分别切,每个字重一份 CSS。这几份 CSS 的 font-family 用同一个名字,font-weight 各不相同,写法见《写对 @font-face:字体名、字重和 local()》。
分片的代价
- 请求数变多。HTTP/2 和 HTTP/3 下影响不大;
- 同一个词的几个字可能落在不同分片里,先后到达时会看到字逐个替换;
- 跨分片的连字、上下文替换可能失效,这对中文影响较小,对西文连字、阿拉伯文等影响较大。
写对 @font-face:字体名、字重和 local()
适合谁看:自己写
@font-face、或自己部署多字重字体的开发者。
@font-face 写错了,浏览器多半不会报错,只会悄悄用错字体、自己加粗,或者多下载文件。下面是几条容易忽略的正确写法。
一个家族,一个名字
同一款字的不同字重,font-family 应该写同一个名字,用 font-weight 区分:
@font-face {
font-family: "My Sans";
src: url("my-sans-regular.woff2") format("woff2");
font-weight: 400;
font-display: swap;
}
@font-face {
font-family: "My Sans";
src: url("my-sans-bold.woff2") format("woff2");
font-weight: 700;
font-display: swap;
}
这样页面里写 font-family: "My Sans",正文自动用 400,<strong>、<h1> 自动用 700。
如果每个字重起不同的名字(如 "My Sans Regular"、"My Sans Bold"),浏览器会把它们当成两款字。给 <strong> 加粗时,它找不到同名的 700,就会把 400 人工加粗,效果很差。
字重数值要和文件对应
font-weight 要写这个文件实际的粗细。常见对应关系:
| 数值 | 常见名称 |
|---|---|
| 100 | Thin、Hairline |
| 200 | ExtraLight、UltraLight |
| 300 | Light |
| 400 | Regular、Normal |
| 500 | Medium |
| 600 | SemiBold、DemiBold |
| 700 | Bold |
| 800 | ExtraBold、UltraBold |
| 900 | Black、Heavy |
字体文件 OS/2 表里的 usWeightClass 记录了厂商给的数值,可以用它来对照。
两点要注意:
- 同一个名字下,两条
@font-face不要声明相同的字重和样式。 浏览器会按自己的规则选一个,结果不可控。 - 只有一档的字,就只声明这一档。 不要把一份 Bold 文件声明成 400,也不要给只有一档的字加
font-weight: bold。可以用font-synthesis: none禁止浏览器人工加粗和拉斜,见《在 CSS 里使用:字体名、备用字体和多字重》。
可变字体写一个范围
可变字体一个文件包含连续的字重,用两个值写范围:
@font-face {
font-family: "My Sans VF";
src: url("my-sans-vf.woff2") format("woff2");
font-weight: 100 900;
}
local() 的正确写法
local() 让浏览器先找用户电脑上装好的同名字体,找到了就不下载。写法要点:
- 括号里写字体的完整名称(Full Name)或 PostScript 名,不是家族名;
- 一个
local()只写一个名字,有多个候选就写多个local(),用逗号隔开; - 名字加引号。
src: local("Source Han Sans SC Regular"),
local("SourceHanSansSC-Regular"),
url("source-han-sans-sc-regular.woff2") format("woff2");
什么时候不要用 local():
- 字体被拆成很多分片时,本地装的版本可能和分片的版本不同,字形、字距、覆盖的字都可能不一致;
- 名字太常见时,可能匹配到用户电脑上另一款同名字体。
拿不准就不写 local(),只写 url()。
记得 format()
format("woff2") 告诉浏览器文件格式,不支持的格式会直接跳过,不会白白下载。今天所有主流浏览器都支持 WOFF2,一般只提供 WOFF2 就够了。
加载策略:font-display、预连接和预加载
适合谁看:已经能用上网页字体,想让首屏更快、闪动更少的前端开发者。
font-display 怎么选
| 取值 | 等待字体(期间不显示文字) | 换成新字体的时机 | 适合 |
|---|---|---|---|
auto |
由浏览器决定,常见是 block |
— | 不建议依赖 |
block |
较长,规范建议约 3 秒 | 字体到了就换 | 图标字体等不能用别的字体代替的场合 |
swap |
极短 | 字体到了就换,不限时间 | 中文正文、标题的默认选择 |
fallback |
极短 | 约 3 秒内到了才换,晚了这次就不换 | 正文,希望减少晚到的跳动 |
optional |
极短 | 基本只在字体已缓存时使用 | 字体可有可无、最在意稳定的页面 |
中文字体体积大、首访很难在 100 毫秒内到达,optional 的结果常常是首访看不到字体。一般选 swap,再用《减少跳动:后备字体和尺寸调整》 里的方法降低跳动。
预连接
字体放在另一个域名时,在 <head> 前部加:
<link rel="preconnect" href="https://字体域名" crossorigin>
浏览器会提前完成 DNS、TCP、TLS 握手。字体请求是匿名跨域请求,所以要带 crossorigin。
预加载:只用在确定的那一个文件上
<link rel="preload" href="/fonts/title.woff2" as="font" type="font/woff2" crossorigin>
- 适合:用固定文字裁出来的标题字体、整个西文字体文件等,确定首屏一定会用到的文件。
- 不适合:按
unicode-range分片的中文字体。页面需要哪几片,要等排版时才知道,手动预加载的那一片多半用不上,反而和关键资源抢带宽。 - 预加载的字体请求即使同源也必须带
crossorigin,否则会下载两次。
用 JavaScript 控制(可选)
字体加载 API 可以检查和等待字体:
// 等页面上所有字体加载完成
await document.fonts.ready;
// 主动加载某个字重
await document.fonts.load('700 1em "My Sans"');
// 检查是否已可用
document.fonts.check('16px "My Sans"');
适合「字体到了再执行动画」「截图前确保字体已加载」这类场景。普通页面用 CSS 就够了。
缓存
字体文件很少变化,建议给它们设置长期缓存(例如一年),文件内容变了就换文件名。
减少跳动:后备字体和尺寸调整
适合谁看:用了
font-display: swap,但字体换上来时页面「跳一下」,想减少布局偏移(CLS)的开发者。
为什么会跳
备用字体和网页字体的字宽、上下留白不同。换字体时,一行能放下的字数变了,行高也可能变了,后面的内容就整体移动。
对中文来说:
- 汉字基本都是等宽的方块,中文部分的字宽差别不大;
- 差别主要来自西文、数字、标点的宽度,以及行高;
- 如果没有写死
line-height,浏览器按字体自带的上下高度计算行高(line-height: normal),换字体后每行高度都可能变化。
第一步:写死行高
给正文写一个明确的行高,行高就不再依赖字体:
body { line-height: 1.75; }
这是最简单、效果最明显的一步。排版上的行高建议见《正文用字:字号、行距和字重》。
第二步:选接近的备用字体
备用字体和网页字体越接近,跳动越小:
- 黑体类网页字体,备用写系统黑体(苹方、微软雅黑、思源黑体 / Noto Sans CJK);
- 宋体、楷体、仿宋类,备用写系统同类字体,见《中文字体栈怎么写》。
第三步:用尺寸调整描述符微调
可以为备用字体单独写一条 @font-face,用描述符把它「调」得更像网页字体:
@font-face {
font-family: "My Sans Fallback";
src: local("PingFang SC Regular"), local("Microsoft YaHei");
size-adjust: 100%;
ascent-override: 88%;
descent-override: 12%;
line-gap-override: 0%;
}
body { font-family: "My Sans", "My Sans Fallback", sans-serif; }
| 描述符 | 调整什么 |
|---|---|
size-adjust |
整体缩放字形 |
ascent-override |
基线以上的高度 |
descent-override |
基线以下的高度 |
line-gap-override |
行间额外空隙 |
上例中的百分比只是示意,要按两款字的实际度量计算。
浏览器支持情况(据 MDN 兼容性数据):size-adjust 在 Chrome 92、Firefox 92、Safari 17 起支持;ascent-override 等三项在 Chrome 87、Firefox 89 起支持,Safari 正式版尚未支持。不支持的浏览器会忽略这些描述符,不会出错。
怎么量
- Chrome 开发者工具「性能」面板,或 Lighthouse,查看 CLS(累计布局偏移);
- 对比开启和关闭网页字体时的截图。
中文字体栈怎么写
适合谁看:要给中文网站写
font-family的前端开发者,不管有没有用网页字体。
字体栈是什么
font-family 可以写一串字体名,浏览器从左到右找,逐个字符判断:第一个字体里没有这个字,就用下一个字体显示这个字。所以字体栈既是「首选不在时的备选」,也是「首选缺字时的补字」。
常见系统中文字体
| 系统 | 黑体类 | 宋体类 | 楷体类 |
|---|---|---|---|
| macOS、iOS | PingFang SC(苹方) | Songti SC(宋体-简) | Kaiti SC(楷体-简) |
| Windows | Microsoft YaHei(微软雅黑) | SimSun(宋体) | KaiTi(楷体) |
| Android | 系统自带,通常是 Noto Sans CJK / 思源黑体,部分厂商用自家字体 | 视机型而定 | 视机型而定 |
| Linux 桌面 | Noto Sans CJK SC、Source Han Sans SC、WenQuanYi Micro Hei 等 | Noto Serif CJK SC 等 | 视发行版而定 |
不同系统版本、不同厂商的预装字体有差别,上表只是常见情况。macOS 上的部分字体需要在「字体册」里下载后才能用。
推荐写法
黑体类:
font-family: "网页字体名", -apple-system, "PingFang SC", "Hiragino Sans GB",
"Microsoft YaHei", "Noto Sans CJK SC", "Source Han Sans SC", sans-serif;
宋体类:
font-family: "网页字体名", "Songti SC", "Noto Serif CJK SC", "Source Han Serif SC",
"SimSun", serif;
几个要点
- 西文字体写在中文字体前面,可以让英文、数字用西文字体,中文落到后面的中文字体上。反过来写,中文字体自带的西文会被用上。
- 最后一定要写通用族名:
sans-serif、serif、monospace。 - 名字有空格要加引号。
- 英文名比中文名可靠。 部分浏览器和系统只认英文名,写了中文名(如「微软雅黑」)可以和英文名并列,但不要只写中文名。
system-ui会用系统界面字体,在中文环境下效果因系统而异,用在界面组件上比用在长文正文上更合适。
缺字的情况
生僻字、新收录的扩展区汉字,系统字体也可能没有。要保证这些字能显示,可以在字体栈末尾加一款覆盖范围大的字体,见《网页和系统里怎么显示生僻字》。
用文风网页字体:一页看懂正确接法
适合谁看:准备在网站上用文风网页字体,想一次把关键做法看全的开发者和站长。
本页是要点汇总,细节在《文风开发者文档》各页。
地址
https://cn.windfonts.com/fonts-packages/{目录名}/{字重}/{子集}/result.css
{目录名}:字体页网址最后一段,小写;{字重}:照抄字体页上的字重名,区分大小写;{子集}:full、zh、zh-common、en。只有full每款字都有,其他子集用前先在浏览器打开确认。
详见《网页字体地址规则》。
推荐的引入代码
<!-- 本页嵌入的字体由文风字体(Windfonts)提供,可自由使用;请保留本授权标注 https://wenfeng.org/license -->
<link rel="preconnect" href="https://cn.windfonts.com" crossorigin>
<link rel="stylesheet" href="https://cn.windfonts.com/fonts-packages/xwwk/Regular/full/result.css">
- 第一行授权注释请保留,见《保留授权注释》;
- 预连接
cn.windfonts.com; - 用
<link>引入,首屏字体不要用@import。
字体名:从 CSS 里复制
不同字体 CSS 里声明的 font-family 名字格式不一样。在浏览器里打开 result.css,搜 font-family,复制引号里的名字,不要按目录名或字体中文名去猜。
body {
font-family: "从 CSS 里复制的名字", "PingFang SC", "Microsoft YaHei", sans-serif;
line-height: 1.75;
}
多字重:先看 CSS 里的数值
每个字重一份 CSS。引入多份之前,打开每份 CSS 看 font-weight 的数值:
- 数值不同,就可以放心一起用,页面里用
font-weight切换; - 数值相同,只引入其中一份,否则后引入的会覆盖先引入的;
- 只有一档的字,不要再加粗、加斜,可以加
font-synthesis: none。
已经帮你做好的事
- 字体已经按
unicode-range拆成很多 WOFF2 分片,浏览器只下载用到的; - CSS 里每条
@font-face都写了font-display: swap; - CSS 和分片都允许跨域引用,并带长期缓存头。
不需要、也不建议做的事
- 不要预加载某个分片,原因见《加载策略:font-display、预连接和预加载》;
- 不要把 CSS 里的分片地址抄到自己的 CSS 里,分片文件名可能随字体更新而变化;
- 想放在自己服务器上,用整套切片包,见《自托管切片与 WordPress 主题》。
先看许可
文风收录的字体许可各不相同。上线前打开字体页的许可原文,确认网页使用在许可范围内,见《这款字能不能商用:五步自查》。
自托管网页字体的许可要点
适合谁看:打算把字体文件放在自己服务器上做网页字体的开发者、站长和企业法务。
网页字体是一种「分发」
网页字体的原理是让访客的浏览器下载字体文件。从许可的角度看,你在把字体文件提供给每一位访客。所以:
- 商业字体:桌面授权一般不包括网页使用,要买网页授权。网页授权常按访问量、域名或年费计价,以厂商条款为准;
- 开源字体:OFL 明确允许用
@font-face做网页字体(OFL-FAQ 2.1),但要满足许可条件; - 厂商免费字体:有的允许网页使用,有的要求只能从官网下载、不得再分发或修改,要逐条看。
OFL 字体自托管的四个要点
- 保留版权和许可信息。 字体文件内部的版权、许可字段不要删;拆子集时加上保留名称表的选项,见《动手拆子集:pyftsubset》。
- 转 WOFF2 不一定算修改,拆子集一定算修改。 只做 WOFF2 压缩、数据和元数据完整保留,可以不算修改(OFL-FAQ 2.2);拆子集、删掉排版功能都是修改(OFL-FAQ 2.6)。
- 修改版不能用保留字体名。 字体声明了保留名的,拆过子集的版本要改名,除非能做到「功能等价」或者和作者另有约定(OFL-FAQ 2.7、2.8)。
- 网站条款不能收紧 OFL。 你可以对字体文件做防盗链,但不能宣称别人不能按 OFL 使用这款字(OFL-FAQ 1.17、1.24)。
逐条解读见《SIL 开放字体许可证(OFL)逐条读》。
改名怎么改
改的是字体文件内部的名字(名称表里的家族名、完整名、PostScript 名),以及你 CSS 里 font-family 的名字。可以用 fontTools 修改,见《fontTools 入门:查看、修改、转格式》。新名字不要包含原字体的保留名。
页面上要不要署名
OFL 不强制在网页上署名(OFL-FAQ 1.1.2)。但在网站的「关于」或页脚写明所用字体和许可,对访客和作者都友好。
使用文风的切片包
文风提供部分字体的切片包,许可仍然以每款字的许可原文为准,切片包里的授权注释请保留,见《自托管切片与 WordPress 主题》。
字体没生效?一套排查顺序
适合谁看:网页字体「好像没用上」「只有部分字变了」「变粗了」,想自己查原因的开发者。
文风网页字体的专门问答见《开发常见问题》。本页是通用的排查顺序,自托管、第三方字体也适用。
1. 看渲染字体
Chrome 或 Edge:开发者工具 →「元素」→ 选中文字 →「计算样式」面板拉到底,看「渲染字体(Rendered Fonts)」。它列出这段文字实际用了哪些字体、各显示了多少个字。
Firefox:开发者工具 →「检查器」→「字体」面板,可以看到页面用到的字体和来源。
- 显示的是系统字体 → 网页字体没加载或名字没对上,继续往下查;
- 网页字体和系统字体各占一部分 → 缺字或分片没加载完,见第 4 步。
2. 看网络请求
「网络」面板筛选「字体」和「CSS」,刷新:
| 看到的情况 | 可能原因 |
|---|---|
| 没有任何字体请求 | font-family 名字和 @font-face 不一致;或页面上没有文字用到它 |
| 404 | 地址拼错,大小写不对,或子集不存在 |
| 请求被拦截,控制台有 CORS 报错 | 字体服务器没有返回允许跨域的响应头 |
| 200,但文件很小或类型不对 | 服务器返回了错误页面,打开地址看看内容 |
3. 核对名字
font-family 里写的名字必须和 @font-face 里声明的完全一致(大小写、空格、连字符)。用第三方 CSS 时,打开 CSS 复制名字,不要凭印象写。
4. 部分字是别的字体
- 用了只含常用字或只含中文的子集,生僻字、西文落到了备用字体;
- 字体本身没有这个字,见《繁体、日文、生僻字显示成方框怎么办》;
- 分片还在下载,等一会儿就会换掉。
5. 字被人工加粗或拉斜
- 页面要求的字重或斜体,在
@font-face里没有对应的声明,浏览器就自己合成; - 不同字重起了不同的家族名,见《写对 @font-face:字体名、字重和 local()》。
6. 用控制台确认
在开发者工具的控制台里运行:
document.fonts.check('16px "字体名"') // true 表示已可用
[...document.fonts].map(f => [f.family, f.weight, f.status])
7. 清缓存再试
字体更新后,浏览器和服务器缓存可能还是旧文件。用无痕窗口或「停用缓存」再试一次。
可变字体和增量字体传输
适合谁看:关注网页字体新技术、想知道哪些现在能用、哪些还要等的开发者。
可变字体:现在就能用
可变字体(Variable Font)把一个家族的多个字重(以及宽度、倾斜等)放进一个文件,用「轴」连续调节。
- 浏览器支持已经很普遍;
- CSS 里用
font-weight: 100 900声明范围,页面里可以用任意中间值,如font-weight: 450; - 也可以用
font-variation-settings调节字体自定义的轴。
中文可变字体的取舍:
- 思源黑体、思源宋体等都提供可变字体版本;
- 一个可变字体文件通常比单个字重大,但比多个字重加起来小;
- 页面只用一两个字重时,单独的静态字重分片往往更省流量;用三个以上字重,或需要动画、细调时,可变字体更有优势;
- 可变字体同样可以拆子集、分片。
字重的设计知识见《多字重家族和可变字体怎么挑》。
增量字体传输(IFT):还在路上
增量字体传输(Incremental Font Transfer,IFT)是 W3C 正在制定的标准。它的思路是:浏览器先下载字体的一小部分,页面需要更多字符时,再下载「补丁」扩展同一个字体文件。
和今天的 unicode-range 分片相比,它的好处是:
- 字体始终是一个完整的字体,连字、上下文替换等排版功能不会因为分片而失效;
- 能更精细地按需下载,对中日韩字体意义很大。
现状(截至 2026 年 10 月):W3C 已发布候选推荐草案(2026 年 10 月 13 日版);Chrome 已表示有意开始原型开发,主流浏览器尚未正式支持。现阶段中文网页字体仍然用 unicode-range 分片。
OFL 常见问题也专门讨论了 IFT:用 IFT 这类按需子集技术提供 OFL 字体是可以的,前提是达到足够的「功能等价」,不能破坏字符覆盖和排版功能(OFL-FAQ 2.9)。