REMY

Chief Designer
迈致品牌创始人

作为一家极致的品牌设计公司,迈致品牌一直在追迹完美的道路上不断探索。
迈致愿凭己之力,以极致的设计让世界变得更美好。

中文作为世界上最博大精深,最不易学习的一门语言,包含了上万个字符。要知道,英文只有26个。

中文庞大的字符集导致了中文字体异常巨大,以 Adobe 联合 Google 发布的 Source Han Sans 思源黑体为例,单个字重为 Eltra-light 的超细体已近20MB,7种字重联合达上百兆。数十、上百兆的中文字体加载在网页中将严重影响访问体验,浏览器将耗费相当的时间下载、渲染,加载完一个网页需要耗时数十秒甚至数分钟,自定义中文字体用在网页上显然是不现实的。

中文字体这么大,目前网页中的中文是怎么显示的呢?

操作系统预置字体。通俗来讲,电脑或手机有什么字体就用什么字体。例如Windows 7/8/10的 微软雅黑、微软正黑,Android的Driod Sans Fallback、Roboto ,iOS/Mac OS的Hiragino Sans、苹方等。网页前端工程师只能在每种设备预置的字体中选择作为中文显示的默认字体。这直接导致了不同平台的同一网页字体不尽相同,用户体验参差不齐,在部分没有合适字体的操作系统上,可以说是“惨不忍睹”。

对于设计师来说,这更是无法接受的。字体在设计中对氛围的渲染、对整体风格的确立都起到举足轻重的作用,很多情形下,甚至可以说没有好的字体就没有好的设计。数年来,迈致品牌也一直在寻求解决方法,希望能将中文字体应用到网页当中,打破网页无中文webfonts的现状。随着设备终端硬件不断进化,HTML5、CSS3得到普及,IE系列浏览器即将绝迹,目前也已经出现数种中文Webfonts解决方案,遗憾的是,没有任何一种方案能做到较高的可用度。

目前主流的解决方案是字体动态裁剪技术,即通过JavaScript向服务器后台动态提交需要渲染的文字,由服务器裁剪并生成字体并返回给浏览器。据测试,这种方案根据文字的数量,可将字体剪裁至数KB-几十KB!目前能提供此技术的服务商仅有 Adobe Typekit / 有字库 / 方拓字体 / justfont 数家。

因动态字体剪裁技术需要耗费大量服务器资源,除 Adobe Typekit 外,其余几家服务商均有网页字数限制,最高仅支持单页600字,对于动辄上千字的网页来说显然不够用。并且由于使用这些服务商的动态字体均属于外部资源,服务器不受控制。一旦服务商服务器离线,将导致网站访问缓慢,网页不能正常显示。而稳定性最好的 Adobe Typekit 因服务器在海外,速度和链接均不能得到保证。

今年,Google Fonts提出了新的解决思路。Google使用机器学习将常用的中文字裁切成了数百个切片,这种方法无需耗费服务器资源,但需要浏览器支持unicode-range属性,目前较新版本的现代浏览器均已支持。

By scanning webpages in Chinese, we model which characters are most likely to appear together, which informs a static subset slicing strategy that sorts all 44,683 glyphs into 102 slices.

但通过源码分析,迈致发现此方法常用的单字重切片字体也近数百KB,一个网页的字体的总大小在数MB左右。目前Google Fonts的服务器已经指向国内,Google也在不断优化这项服务。如果不是很在意网页载入速度和浏览器支持,可以尝试。

根据以上的研究和分析,字体动态裁剪技术是目前可行性最高的解决方案。但动态字体剪裁技术是各个字体服务商的核心技术及盈利保证,其源码并不会开源。

经过不断寻找、测试,迈致终于找了开源的动态字体剪裁方案,感谢Google工程师 甜菜萧,他利用FontForge和php-font-lib和自行编译的PHP及JS实现了动态字体剪裁。迈致在此项目基础上修改,将项目默认输出的ttf字体变更为更符合现代浏览器的woff字体,并解决了此项目因JS HTML DOM导致的文字重新渲染闪烁的FOIT问题,极大提升了用户体验。

部署请参考Github托管的webfonts-subsetting项目: https://github.com/xiaoxq/webfonts-subsetting

Install fontforge, which will be used in subsetting Make sure the php can execute fix_ttf.pe Make sure the php has WRITE access to the font directory Make sure the php has WRITE access to its own directory if you want to see logs

下面主要分享迈致改进的内容:

exec fix_ttf.pe 原作者本意是想通过FontForge修复php-font-lib动态剪裁字体的bug,因ttf老旧已不适合网页字体,迈致将其修改为直接输出woff,目前主流浏览器均支持woff格式,IE系列浏览器即将面临淘汰,不在我们考虑兼容的范围。修改后的代码如下,将其替换即可:

Open($1,1)
SelectAll()
Copy()
Generate($2:r + “.woff” )
Close()

解决FOIT
浏览器显示网络字体前需要先通过网络下载字体,这通常需要一定的时间,并且不同的浏览器在下载网络字体时有不同的行为。一些浏览器在加载字体时隐藏文字,而另一些浏览器会先显示降级字体。这两种方法通常被称为 Flash Of Invisible Text(FOIT)和 Flash Of Unstyled Text(FOUT)。

此方案通过JS在Html的Head中添加Style标签,将剪裁后的字体提交给浏览器,浏览器接收到数据后,会立即加载还未下载的字体,并且新字体加载和渲染需要一定时间,这将导致原本的内容消失,出现文本闪烁现象,这将极大影响用户体验。

迈致的解决思路是:在剪裁字体未渲染之前,将网页原有文本隐藏,通过JS监测文本宽度,一旦文本宽度发生变化,说明剪裁字体已经成功加载,这时JS将原本隐藏的文本通过渐入的方式展现,极大改善了用户体验。

 

代码如下:

// JavaScript Document
var span = document.createElement(“span”);
span.innerHTML = “gW@i#Q!T”;
span.style.visibility = “hidden”;
span.style.position = “fixed”;
span.style.top = “0px”;
span.style.fontSize = “500px”;
document.body.appendChild(span);
var width_now = span.offsetWidth;
var interval_check = setInterval(function() {
if(span.offsetWidth != width_now) {
clearInterval(interval_check);
document.body.removeChild(span);
span = null;
}
}, 10);