关于 Mkdocs Metrial 自定义字体渲染和优化
约 1199 个字 41 行代码 3 张图片 预计阅读时间 5 分钟
wcowin 的博客讲了自定义字体使用的一种方式,ronaldln 的博客讲的更加详细,介绍了多种方法。
但如果你想要用的字体不是 Google Fonts 上有的,手头只有.ttf或者.otf格式的文件,或者你想要更好的字体渲染效果,可以参考下面的做法。
准备自定义字体
本网站在普通文本中使用的中英文字体均为方正兰亭圆 GBK,有纤、细、准、中、中粗、粗、大、特8 个字重,由方正字库提供,模仿了游戏 Blue Archive 的字体风格;代码块内使用字体为Maple Mono CN SemiBold。
方正兰亭圆字体文件和FZLanT.font.css一同保存在我自己的阿里云 OSS 中,使用时仅需调取该 css 文件即可;Maple Mono CN SemiBold 字体文件本体在 jsDelivr 上,在mkdocs.yml中extra_css栏引用即可使用。
除此以外,对于日文、韩文字体,方正兰亭圆 GBK 并不支持,所以调取了基沃托斯古书馆提供的 Blueake 字体。
综上所述,自定义字体需要准备css文件和字体文件两部分:
css文件可以放在本地docs/stylesheets/目录下,也可以放到服务器上,在mkdocs.yml中调取;字体文件最好放在服务器上,在css文件中调取。
mkdocs.yml
| CSS | |
|---|---|
FZLanTY.font.css
自定义字体的引用
网站不要设计太多的字体,直接在extra.css中修改root,指定正文和代码块的字体族即可。
Info
排在后面的字体会作为备选字体使用,当前面的字体无法显示时会使用后面的字体。
Warning
有一个坑点,方正兰亭圆 GBK 虽然说是支持 GBK 字符集,但它字符库里的日文和韩文字符是宋体,真尼玛逆天,所以直接这么写会导致日文和韩文字符显示成宋体。因此需要使用 FontCreater 工具将 ttf 字体文件中的日文和韩文字体切片删除掉。
Figure 1. FontCreater 界面
有人会问为什么不直接用 Blueaka,因为 Blueaka 的字重只有 Regular 和 Bold 两种,无法满足不同层级标题和正文的需求。
FZLanTY 字体有 8 个字重,可以根据需要在extra.css中指定不同的字重:
| CSS | |
|---|---|
Info
需要在字体引用的 css 里定义 font-weight 映射的字体。
自定义字体的渲染优化
本文重点其实在这,自定义的字体文件选择什么格式更好,如何渲染带宽更少,都有优化空间。
以方正兰亭圆 GBK 为例,8 个字重的 ttf 文件加起来共 89.8MB,放在网站上显然不合适。并且,ttf 格式的字体在网页上的渲染有锯齿,非常难看。
Figure 2. 使用 ttf 格式的字体渲染
那么有什么优化方式吗?
WOFF2 格式字体
WOFF2(Web Open Font Format 2) 是专门为网页设计的字体格式,具有更好的压缩率和加载速度。将 ttf/otf 格式的字体转换为 woff2 格式,可以显著减少文件大小,同时保持较高的渲染质量。
Figure 3. 使用 woff2 格式的字体渲染
将方正兰亭圆 GBK 的 8 个字重转换为 woff2 格式后,文件大小从 89.8MB 减少到约 15MB,加载速度大幅提升,渲染效果也更佳。
即便如此,15MB 的字体文件对于网页来说仍然太大了。我们可以使用子集化技术进一步优化。
字体子集化
字体子集化是指根据实际使用需求,只保留字体文件中需要的字符,从而大幅减少字体文件的大小。对于只使用部分字符集的网站,子集化可以显著降低字体文件的体积。
但如果删除了想要渲染的字符就完蛋了,因此更好的办法是使用 css 的unicode-range参数,将原始字体文件拆分为数个(甚至几十上百个)woff2 子集文件,每个子集文件只包含特定范围的字符,然后在 css 中使用@font-face分别引用这些子集文件,并通过unicode-range指定每个子集文件对应的字符范围。
| CSS | |
|---|---|
每个子集字体文件仅几 KB 到几十 KB,网页需要渲染什么字符,就加载字符所在的子集文件,这样大大减少了字体传输总大小。实测仅需 710kB 的 woff2 子集文件就能覆盖网站上使用的所有字符。
字体切片推荐使用 font-slice 这个工具,它是根据 Google Fonts 的切片方式设计的,输入 ttf 或者 otf 字体文件自动导出 woff2 子集和对应的 css 引用。


