网页与字体

font-family

我们在 CSS 定义 font-family 的时候,指定的字体可能浏览页面的访客电脑上没有,所以 font-family 本身是一个复合型的列表,如果排在前面的字体没有被匹配到,依次继续匹配。
而考虑到各个操作系统,比如 MacOS、Windows、Ubuntu(Linux) ,为了尽可能达到跨设备、好的阅读体验,一般存在一个接近最佳实践的方案。
课程已经到尾声,按照我们向来的理念,这个 最佳实践 其实是不存在的,仅做参考。比如 Leptureyue.css 就是一个很好的参考对象。

对了,记得很早的时候,曾经遇到一个诡谲的现象,就是本地电脑上有 微软雅黑 这个字体,而且 font-family 也指定了 微软雅黑,不论如何就是无法使用这个字体渲染。
我们在自学的过程中,这种看似诡谲的想象,其实终归会碰到的,开始时候碰到多一些,到后面会少一些,也会逐渐学会如何找到办法解决,或者换种方式绕开。
所以,这个微软雅黑最后怎么处理的呢?很简单呀,换成 "Microsoft YaHei" 就可以了……

WebFont

英文的字体,一般都很小,毕竟归根结底就是字母+数字。
很多页面的设计感,会来自于字体的美感。
很自然,技术人就想到了在 HTML 内直接嵌入字体。在 博客自定义 这节中,其中一个博客模板,有使用过这个效果。
比如 Google 还提供了在线的、免费使用的英文 WebFont,https://fonts.google.com/;当然,众所周知的原因,这个服务是不稳定的 (2019),一般真要使用的时候,需要将这些字体先下载到本地,直接托管于自己的网站之中。

CSS 中引入图片、字体这些资源,可以是直接的 URL 形式,但也有一种特殊的格式叫 base64,可以将资源的字节内容,直接转为 base64 的编码,然后直接压入到 CSS 文件中,因为英文字体一般不大,几十 KB 或者 100KB 左右,直接放入到 CSS 文件中也没有什么问题。

base64 是蛮常用的一种编码,它并不会压缩原始内容,甚至会让原始内容变得更大,但经过转码,不管原始内容是什么样的人类无法阅读的二进制(比如一张图片的原始内容),都会转为普通的文本,那么,就很方便传输了。
比如我们在 HTML 中,Javascript 在 Canvas 上绘制了图片,我们想把它上传到服务器,可以将图片转为 base64 编码,普通的 Ajax 请求就能上传了,而不用特殊构造一个文件上传的逻辑。
还有在一些反复转码的过程,base64 就是兼容性很高的格式。比如说 JSON 格式吧,在 JSON 上直接存二进制原始内容,能做到吗(以我浅薄的认知,应该是做不到的) ?那么我们需要将其转码,base64 就是比较自然的选择之一。

Font ICON

以前,页面上很多修饰性的图标,是直接用图片的。但有个问题,就是修饰的图标很多的情况下,如果一个图标对应一张图片,会导致一个页面内的资源请求数太多,所以,就出现了 CSS Sprites 的技术: 也就是将多个图标合在同一张图片里,然后在单个调用的时候,在 CSS 样式中,将其作为背景图,并设定背景的坐标偏移,就可以了。
现在使用 CSS Sprites 的,应该很少了,技术上来说,不是难点,但真的繁琐。

现在大多数要使用是 Font ICON 这样的技术,实际上,就是一个 font,只是字体集里的字符是一个图标,除了它是矢量可任意缩放的好处之外,更重要的是,它足够方便,也容易理解。
Font ICON 有不少,比如 FontAwesomeIonicons,基本上可以直接拿来就用。
除了在 Web 端使用之外,比如我在创作桌面 App 的时候,也会使用 Font ICON 来处理图标的呈现,因为,需要用到的图标本质就是特定字体的字符而已。

在特定场景下,我们可能需要合并两个字体,或者提取字体中的个别字并最终合并,可以使用FontForge,这个软件用起来还是比较麻烦的。
如果只是选一些自己需要的 ICON 的话,可以使用在线版的 iconfont,它算是阿里旗下的,相信可以为你节省不少时间。

中文字体提取子集

之前我们说过,中文的字体太大了,每个文字对应一个字形,可想而知字库有多大。
一个页面内用到的文字总数又是有限的,如果在一个页面中引入整个中文字体,明显很浪费,而且一个页面的背后是几十 MB 大小的字体,非常不现实。
设计感有时候来自于字形的美感;怎么把好看的中文字形,应用于网页设计中呢? 这个问题最简单的办法是: 将文字导出为透明的 PNG 图片,就可以了……

我们对于 技术 本身,虽然有不少不在乎的地方,但有些技术方案,仍然会追求更简洁、更通用、更自然的处理方式。
除了将文本转为图片的方法之外,我们更想实现的,是提取一个指定字体的子集,只包含指定的文字就可以了。如此一来,一个页面可能用到的文字字体,几百个 KB 就够了 (相当于一张图片大小)。
字体子集的好处毋庸置疑:

  1. 不是图片,仍是文本,可以选择、复制;
  2. 容易被识别(包括被搜索引擎识别),不然有些场景要面对搜索引擎,还要另外构建隐藏起来的 DOM 元素;
  3. 文字是矢量的,放大、缩小基本不会变形,在跨设备的时候,不用特殊对应。

Google 旗下有个开源的库 sfntly,可以编辑、构建特定的字体,将其编译后,内部有一个程序叫 sfnttool.jar,可以用来提取字体的子集并形成新的字体文件。