字体介绍
可参考这篇文章 介绍
字体文件格式:
TTF 包含一个单独的字体样式文件(普通、斜体、粗体)等
OTF 它基于支持扩展字符集(连字、替代样式、字形等)的 TrueType 格式
WOFF 这个字体格式使用zlib压缩,文件一般比ttf小40%左右
WOFF2 使用Brotli方法压缩,在woff基础上进一步优化了体积
背景介绍
当我们在页面中引入自定义字体的时候,使用 @font-face 设置, 如果自定义字体包特别大的话,会导致页面在渲染的时候,出现字体加载空白问题,也就是所谓的 FOIT (Flash Of Invisible Text) 会发现页面结构和图片出来了,但是文字区域是空白的
这是因为当使用font-face下载字体的时候,浏览器需要等文件下载完成后,并且还要去解析页面内容,看文档中有没有节点使用了@font-face 的字体,才去决定是否需要下载字体。当浏览器开始下载字体,使用了该字体的所有文本会被隐藏,导致页面出现空白
解决方案
为了解决 FOLT 这种现象,我们可以使用css的font-display可以解决此问题
css的font-display有五个值,分别是
auto: 使用浏览器默认的行为;
block:浏览器首先使用隐形文字替代页面上的文字,并等待字体加载完成再显示;
swap:如果设定的字体还未可用,浏览器将首先使用备用字体显示,当设定的字体加载完成后替换备用字体;
fallback:与 swap 属性值行为上大致相同,但浏览器会给设定的字体设定加载的时间限制,一旦加载所需的时长大于这个限制,设定的字体将不会替换备用字体进行显示。 Webkit 和 Firefox 中设定此时间为 3s;
optional:使用此属性值时,如果设定的字体没有在限制时间内加载完成,当前页面将会一直使用备用字体,并且设定字体继续在后台进行加载,用于下一次浏览时可以直接使用设定的字体。
除了 css 的 font-display 外,还提供了 FontFaceSet 接口加载字体,还可以使用js 监听加载事件,当字体加载完成后替换class,效果如同 font-display: swap 效果。这里不再过多介绍
使用上面办法优化后,会发现还会有另外一个问题,字体加载完成之后,页面闪了一下,这是因为备用字体和自定义字体外形差距太大导致的,这种现象又称为 FOUT (Flash Of Unstyled Text)
我们可以通过缩小字体体积,以及优化加载速度来进行优化
字体加载优化方案
预加载
通过预加载 web 字体提高加载速度
<link rel="preload" href="https://font.com/myFont.woff2" as="font" type="font/woff2" crossorigin>
as="font" type="font/woff2"属性会告诉浏览器将此资源作为字体下载,并帮助确定资源队列的优先级。
crossorigin 属性说明是否应使用 CORS 请求获取资源,因为字体可能来自不同的域。如果不设置此属性,浏览器将忽略预加载的字体。
利用 fontfaceobserver 判断字体加载完成
npm i fontfaceobserver
// 可参考链接: https://juejin.cn/post/6844903431832862728
// css 中 @font-face 已定义好
import FontFaceObserver from 'fontfaceobserver'
loadfont(){
console.time("字体加载用时")
var ooo = new FontFaceObserver('Regular')
ooo.load().then(() =>{
document.getElementById('index').style.fontFamily = 'Regular'
console.timeEnd("字体加载用时")
})
},
设置 font-display: fallback,同时 preload web font,尽可能在 100ms 内加载完网络字体。
// 优先查找本地系统中是否存在 Alegreya 字体,没有再去加载字体文件。
@font-face {
src: local("Alegreya"),
url("./fonts/Alegreya/static/Alegreya-Bold.ttf") format("truetype");
}
字体体积优化方案
1. ttf 转 woff2
使用 node 工具库,将 ttf 格式字体转换为 woff2 格式
npm install ttf2woff2 -g
cat PingFangBold.ttf | ttf2woff2 > pingfangblod.woff2
2. 使用 Fontmin
具体使用参考: ecomfe.github.io/fontmin/
3. 使用 font-spider
为了压缩字体体积,将页面字体单独提出压缩出一份新的字体文件。
例如: 0123456789课程前瞻 是页面中用到的 PingFangRegular.ttf 的字体
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<style>
@font-face {
font-family: 'pingfangregular';
src: url('./PingFangRegular.ttf');
font-weight: normal;
font-style: normal;
}
div {
font-family: 'pingfangregular';
}
</style>
<body>
<div>
0123456789课程前瞻
</div>
</body>
</html>
利用 font-spider 将这几个字体提取出来组成一份新的字体
npm install font-spider
font-spider index.html