中文网页字体设置

中文网页字体设置

由于中文字体通常体积较大,在 web 中使用中文字体确实需要一些技巧。我也一直在纠结使用什么样的字体能有更好的阅读体验,鼓捣过 Typekit 加载思源宋体,可难免会拖慢加载速度,有时还不能成功加载,只能换回系统内置字体。今天就好好研究下网页字体的使用,一劳永逸!

网页字体起源

先来看看 1993 年的网页长什么样:

NCSA MOSAIC™, source: http://www.ncsa.illinois.edu/enabling/mosaic

这是历史上第一款可以显示图片的 Web 浏览器 NCSA Mosaic 的截图,它仅包含单一的、默认的字体。其实看起来还挺不错的,就是斜体字不太清楚。从那时起浏览器在字体渲染方面就在不断进步,尤其是英文字体,已经可以用 “pixel perfect” 在网页中呈现;但是中文字体在这方面却要远远落后。

NCSA Mosaic 刚发布时,它只能用默认字体,没法让网站开发人员指定网页使用什么字体。直到 1996 年微软发布 IE 浏览器、 Netscape 浏览器(NCSA Mosaic 前身)发布版本 3.0,一个叫 FONT FACE 的属性被引入进来用于网页开发者指定字体,这时,网页上使用字体的故事才真正开始。

当时,IE 提供的 FONT FACE 属性可以这样指定字体:

<FONT FACE=font name, 2nd choice, 3rd choice>
  text goes here
</FONT>

微软给出的说明:

The FACE attribute relies on at least one of the fonts specified being installed on the reader’s system. If the first choice of font is not present on the reader’s computer then the second choice font will be used. If none of the listed fonts are present then the user’s own default font will be used.

虽然给出了字体选择的方案,但当时微软的 Windows 95 也只有 Arial、Courier New、Times New Roman 三种可以用于正文渲染的字体(typeface),可能用户操作系统默认是用 Arial 字体,网页上可自定义的字体也只是比 FONT FACE 出现之前多了 Courier New、Times New Roman 两个选择而已。

网络字体的出现

直到 1998 年, IE 4 浏览器终于提供了 @font-face 的 css 规则以允许在网页上加载网络字体文件,使页面显示字体不再依赖用户的操作系统内置字体。但这要借助微软官方提供的字体压缩工具将 OpenType TT(.ttf) 格式的字体压缩成 .eot (Embedded OpenType) 格式。看一下其引用格式:

<style>
  @font-face {
    font-family: Lora;
    src: url(lora.eot);
  }
</style>

这已经和现在的引用格式一样了。可是当时引用网络字体渲染出来的文字效果不佳,另外,那时的网速慢导致网络字体的体验很差,这一特性遗憾地没流行开来。所以有很长一段时间网页上用字体还是要看安全字体,使用有限的几种安全字体组合。

直到 2007 年苹果推出 Safari 3.1 浏览器,提供了更优秀的 @font-face 加载的网络字体渲染效果。随后两三年内 Firefox、Chrome、Opera 等主流浏览器都支持了这一规则。相比 IE 浏览器只支持 .eot 字体格式,这些浏览器支持使用范围更广、更常见的 TrueType 与 OpenType 字体格式。下表是来自 w3schools 的网络字体支持情况。

Font formatIE / EdgeChromeFirefoxSafariOpera
TTF/OTF9.0*4.03.53.110.0
WOFF9.05.03.65.111.1
WOFF2Not supported36.035.0*Not supported26.0
SVGNot supported4.0Not supported3.29.0
EOT6.0Not supportedNot supportedNot supportedNot supported
  1. *IE: The font format only works when set to be “installable”.
  2. *Firefox: Not supported by default, but can be enabled (need to set a flag to “true” to use WOFF2).

这一举措也让字体厂商开始担心字体在网页上被下载盗用,2009 年顺势而出的网络字体服务 Typekit 解决了开发者在网页上引用字体的版权问题,这些变化让网络字体进入了新的时代。

2010 年 Google 推出了 Google Fonts 服务,提供了大量自由使用的字体,让 @font-face 引用网络字体更自由方便。之后相继冒出了 Fontdeck 、Webtype、fonts.com 等大量网络字体服务网站。大量网站使用网络字体促使了浏览器更好地兼容这一特性,而浏览器更好的兼容性又推动了开发者乐于使用 font face 技术实现一些工具。

2011年 4 月 Google Fonts 还推出了字符集子集的服务,引入 text= 参数让 Google Fonts 根据传入的 text 值生成字体子集。后续 Google Font 团队又把这种处理字体子集的 sfntly 工具开源出来,其处理速度号称可在毫秒级别完成大型字体的字体子集处理。除此之外,被广泛采用的字体处理技术还有 2009 年出现的使用 perl 开发的开源项目—— Philip Taylor 的 Font Optimizer,以及使用 python 开发的一些 fontforge 处理类库。

但是,以上这些都只是针对英文网络字体现实的。

中文网络字体

相比通常只有几十 KB 的英文字体,网页加载一个 GB2312 的中文字体至少要增加 2 MB 以上加载量,而大部分中文字体都在 5 MB 以上。所以网络字体在国内没有流行起来,还是要像英文网页好多年前一样,用网页安全字体。

下表可以看到各系统预置的中文字体——各系统根本没有相同的字体,即没有网页安全中文字体!

系统预置中文字体
Mac OS X华康苹方(10.11 开始)
冬青黑体: Hiragino Sans GB (10.6 开始)
华文细黑:STHeiti Light (又名STXihei)
华文黑体:STHeiti
华文楷体:STKaiti
华文宋体:STSong
华文仿宋:STFangsong
Windows微软雅黑: Microsoft YaHei(Windows 7开始)
黑体: SimHei
宋体: SimSun
新宋体: NSimSun
仿宋: FangSong
楷体: KaiTi
仿宋GB2312: FangSong_GB2312
楷体GB2312: KaiTi_GB2312
AndroidDroid Sans Fallback
iOS苹方(iOS 9开始)
黑体:Heiti SC (iOS 8)
华文黑体:STHeiti(iOS 7.0 及以下)

而英文字体到 2016 年有了 20 多个安全字体1,已沉淀了很多种可靠的字体组合方式2

在各系统提供统一中文字体之前,还是要用很长的组合字体方案实现比较完美的显示3

/* 黑体 */
font-family: -apple-system, "Helvetica Neue", Helvetica, "Nimbus Sans L", Arial, "Liberation Sans", "PingFang SC", "Hiragino Sans GB", "Source Han Sans CN", "Source Han Sans SC", "Microsoft YaHei", "Wenquanyi Micro Hei", "WenQuanYi Zen Hei", "ST Heiti", SimHei, "WenQuanYi Zen Hei Sharp", sans-serif;

/* 楷体 */
font-family: Baskerville, Georgia, "Liberation Serif", "Kaiti SC", STKaiti, "AR PL UKai CN", "AR PL UKai HK", "AR PL UKai TW", "AR PL UKai TW MBE", "AR PL KaitiM GB", KaiTi, KaiTi_GB2312, DFKai-SB, "TW\-Kai", serif;

/* 宋体 */
font-family: Georgia, "Nimbus Roman No9 L", "Songti SC", STSong, "AR PL New Sung", "AR PL SungtiL GB", NSimSun, SimSun, "TW\-Sung", "WenQuanYi Bitmap Song", "AR PL UMing CN", "AR PL UMing HK", "AR PL UMing TW", "AR PL UMing TW MBE", PMingLiU, MingLiU, serif;

/* 仿宋 */
font-family: Baskerville, "Times New Roman", "Liberation Serif", STFangsong, FangSong, FangSong_GB2312, "CWTEX\-F", serif;

随着 Google Fonts 的 sfntly 字体子集工具的开源,字体子集技术开始在 web 开发业界流行起来。2013 年开始国内 web 开发社区上讨论中文字体子集化的相关问题慢慢增多,比如小米一些产品介绍页面使用自定义的黑体,具体做法是使用 python、java 等脚本把页面中用到的中文字符从完整的字体文件中分离出来组成新的字体,这样极大地减少了字体文件大小,让网页加载中文字体方案变得可用了。国内的 Ruby 社区聚集了很多对新技术狂热的 web 开发者,比如一开始使用 fontcustom 做字体图标处理的 iconfont.cn ,因为字体也是矢量的,既然能根据图标生成字体文件,也就可以根据文字内容按需生成字体文件。于是,iconfont.cn 不久也推出了中文字体子集服务。

而现在,由于 Nodejs 的流行,npm 上已有大量处理字体的模块,国内做字体子集技术的也慢慢以 Nodejs 模块为主。比如百度的 fontmin、aui 的 font-spiderfont-carrier 等。这些字体子集技术,其需求来源大多是展示性较强的产品介绍类网页。这些静态展示的网页内容不会有什么变化,因此会采用预先根据静态的文字生成字体子集文件,往往会把一个 4-5 MB 的字体缩减成 20-30 kb,加载速度自然提升不少。

最近 Adobe Typekit 中提供了思源宋体和思源黑体的动态加载功能,Typekit 脚本会在网页加载完成后再加载字体,并且会根据需要只加载需要的字符,大幅提升速度。但是即使是如此,中文字体的加载还是会相对缓慢,所以不建议大篇幅使用动态字体,文章正文还是使用系统内置字体更好。

但是对于动态变化的页面,这样的技术实现却变得比较复杂。比如我设置的评论系统,如果用户新添加评论中含有原网页不存在的字符,就会以另外的字体展示出来,破坏的网页原有的整体效果。即便是使用 Typekit 的动态加载,这些新内容也需要稍等等才能渲染出来(取决于用户的网速了,Typekit 使用的是 Akamai CDN 服务,在国内的速度差强人意)。对于这种情况,还是使用系统内置字体更佳。

avatar

Frank Lin

Code learning...