Yihui Xie

思源宋体

谢益辉 / 2017-04-20


今天在小黄的日志中了解到思源宋体。我看了一下介绍以及大概的字体样式,觉得终于找到一款能跟苹果系统的宋体媲美的中文字体了,而且是免费开源字体,太难得了,我感到非常欢喜。我自认为对字体的眼光已经很贼,但它的介绍页面上的四个“曜”字的区别我愣是没能找全,有一处差异实在太细微。

衬线字体和非衬线字体二者比起来,我还是更喜欢有棱角的衬线字体,觉得它更有书法美感。所以尽管好几年前思源宋体的兄弟字体“思源黑体”就已经发布,也没能勾起我的兴趣。

前面我曾经说中文字体不适合使用网络字体,因为字体文件体积太大,不像英文,只有有限的字符,通过网络加载字体也不碍事。今天我又重新看了一下 Typekit,我以前一直以为它只有付费服务,今天才发现原来也有免费服务1,而且思源宋体也可以作为网络字体免费加载。当然,它也不可能加载整个字体文件,而是按需加载,也就是先看看你的页面上用了哪些字符,只加载那部分子集,这样就会快很多了。

理论上本文到此就可以结束了,但我注意到用 Typekit 异步加载字体时,字体应用到文字上有两三秒时间的延迟2,这两三秒又是我忍不了的等待。我可以取消异步加载,但那样会拖慢整个页面加载的速度(字体下载完成之前页面会是空白一片),所以只能想办法克服整个延迟,不过异步加载一定会导致字体延迟,这是无法避免的后果,唯一的可能性是将思源宋体安装在本地,然后在浏览器中检测这个字体是否已经安装,如果已安装,就没必要加载 Typekit 给的 JS 脚本了。

于是找有没有检测某个字体是否安装的办法。还真有,而且既简单又有趣,原理大概是用一个 <canvas> 对象装一段文字,先让这段文字以等宽字体(monospace)显示,测量一下宽度;然后换成想要测试的字体显示,再测宽度。如果两个宽度相等,那么要检测的字体应该没安装。因为如果该字体安装了的话,这段文字的宽度应该会不一样。这个不严谨,但两种字体应用在一段文字上出来精确相同的宽度的概率应该非常低。

最终我的方案是检测 Source Han Serif 字体是否已安装3,若已安装则跳过加载网络字体。这意味着各位客官需要在自己的电脑上安装思源宋体。如果安装说明看起来晕,那么苹果用户选 Super OTC 的两个文件下载解压安装;其它系统选对应中国地区的字体下载安装应该也错不到哪儿去。如果本地没有安装思源宋体,那么阅读我的网站的中文页面时4,就会出现字体延迟几秒加载的情况。

各个系统下看了一下渲染效果,仍然是瘟到死系统看起来丑丑的,字形是对的,但不知道为什么比苹果和 Linux 系统下显示的字体都粗,不知道是我的版本问题还是我用虚拟机的缘故。懒得折腾了,为瘟到死系统优化网页显示效果太麻烦。


  1. 当然有些限制条件,但对我们这种小型个人网站来说,一般应该不会超出它的限制条件,比如页面访问量。
  2. 文字先以系统已有的字体显示,等思源宋体的字符都被下载下来之后,才以思源宋体显示,所以会有短暂的字体变化。
  3. 具体实现起来,还需要考虑用户是否安装了特定语言的思源宋体,比如简体中文、繁体中文等。
  4. 我在我的 Hugo 模板作了专门处理,只有以 /cn/ 开头的链接或者首页才尝试加载中文字体,其它页面都不受影响。这也是我尽量坚持的网页设计原则:若无必要,绝不多加载一个文件。