H5字体加载策略优化
随着网页内容的丰富化,我们使用自定义字体来处理漂亮个性化的网页呈现,所以我们会在网页中使用自定义字体,但是也伴随着给我们带来了一些问题,那就是自定义字体比较大,尤其是中文字体,随便就是好几兆,会给用户一种网页加载很慢的感觉,所以针对上述的问题需要做一部分优化:
下面是我项目使用的一些字体的大小:
1、设置 font-display: swap
我们需要在美观和性能之间做一个取舍和平衡点,查看MDN,可以通过font-display的设置去处理;
参考链接:https://developer.mozilla.org/zh-CN/docs/Web/CSS/@font-face/font-display
下表是不同font-display加载速度的对比以及描述:
选项 | 备用字体显示顺序 | 真实字体显示顺序 | 说明 |
---|---|---|---|
auto | 1 | 1 | 字体显示策略由用户代理(浏览器)定义,可能是其他4种的一种,很多浏览器默认的是block。 |
block | 3 | 1 | 为字体提供一个短暂的阻塞周期(3s)和无限的交换周期。 这个短暂的阻塞周期一般是3s,在这3s,自定义字体部分是空白的,iOS默认就是这个选项,导致一进去页面就是空白的。 |
swap | 1 | 1 | 为字体提供一个非常小的阻塞周期(<=100ms)和无限的交换周期。 能很快的展示备用字体,并且等待自定义字体加载完成之后会使用自定义的字体,不管多久加载出来都会替换。 |
fallback | 1 | 没显示 | 为字体提供一个非常小的阻塞周期(<=100ms)和短暂的交换周期(3s)。 和swap类似,但是如果字体加载太慢,时间超过了阻塞周期+交换周期的时间,自定义字体将永远不会显示。 |
optional | 1 | 没显示 | 为字体提供一个非常小的阻塞周期(<=100ms),并且没有交换周期。 在阻塞周期内字体没有加载完成,自定义字体永远不会显示。 基本上不会导致页面闪动,但是并不会取消下载字体。 |
不同font-display对应的加载时间线
- 黑色代表页面上不展示内容的时间
- 红色代表展示备用字体的时间
- 蓝色代表展示自定义字体的时间
通过上面的图可以看到,swap基本不会有展示空白字体的时间,在没有加载完成的时候页面展示的备用字体。
上面提到三个概念:字体阻塞周期、字体交换周期、字体失败周期,加载自定义字体都会经历下面三个阶段,上面设置的font-display相当于配置了每个阶段的时长。
下图展示了加载一个自定义字体的过程。
字体阻塞周期(Block)
如果未加载字体,任何试图使用它的元素都必须渲染不可见的后备字体。如果在此期间字体已成功加载,则正常使用它。在此期间特殊字体部分会展示空白或者错误的字体样式,如果是字体图标就会出现奇怪的符号。
字体交换周期(Swap)
如果未加载字体,任何尝试使用它的元素都必须呈现后备字体。如果在此期间字体已成功加载,则正常使用它。
字体失败周期(Fail)
如果未加载字体,用户代理将其视为导致正常字体回退的失败加载。
使用场景
- 如果字体是用来展示主网页的字体,特殊字体只是装饰性作用的,防止闪动,建议使用optional。
- 如果是客户指定的字体,必须要展示,可以使用swap,在没有加载出来的时候展示备用字体。
- 如果字体是用来展示图标的,建议使用block,在没有加载的时候不展示字体。
2、字体子集化方案 Fontmin,subfont
对于页面中出现的固定文本,可以在字体文件中拆出来,只加载必须要的字体,这样通过裁剪之后的字体的尺寸会大大减少;
可以使用fontmin的Node.js API直接和webpack集成,乐活动模板已经集成。
参考链接
- 通过预加载可选字体来防止布局偏移和不可见文本闪烁 (FOIT)
- 在字体加载期间避免不可见的文本
- Font Face Observer
- Controlling Font Display Per Font-Face: the font-display descriptor
- The Font Display Timeline
- Font-display playground