❗ 本文最后更新于 3895 天前,文中所描述的信息可能已发生改变,请谨慎使用。
Chrome 是我的主力浏览器,总得来说用着还算顺手,但也经常遇上一些让人很恼火的地方,例如万恶的滚动条冻结现象、监管不力乱象丛生的扩展、越来越反人类的新标签页等等。今天要说的是 Chrome(严格说是 webkit)下另外一个严重的问题,与 Web Fonts 有关。
起因
每台电脑都会安装多种字体,网页中可以通过 css 指定页面文本使用哪种字体。Web Fonts 则让浏览器拥有使用从互联网下载的新字体渲染文本的本领。截至到当前,全世界 Alexa 排名前 100 万的网站中,用到 Web Fonts 技术的已经占到 39%。
本文不会介绍如何使用 Web Fonts,本文要讨论的是这样一种场景:
浏览器要渲染使用了 Web 字体的文本,就必须从互联网下载字体。由于网络的不确定性,如果下载字体花费的时间非常久,浏览器该如何处理?
实际上,浏览器能使用的策略并不多,无外乎以下几种:
- 先使用系统默认字体渲染文本;等 Web 字体下载完,使用新字体再渲染一次;
- 等到 Web 字体下载完成,才渲染文本。也就是字体下载完全阻塞对应文本渲染;
- 先跳过文本的渲染;一段时间后,如果 Web 字体仍未下载完,使用系统默认字体渲染文本;等字体下载完,再次渲染;
方案 1 的好处是用户可以第一时间看到文本内容,坏处是:两种字体之间的差异,一定会造成内容抖动。早期的 Firefox 以及现阶段所有 IE 都是采用的这种方案。
方案 2 的好处是完全避免了内容抖动,坏处也很明显:字体下载需要多久,用户就有多久完全看不到文本内容。现阶段基于 Webkit 内核的浏览器,如 Chrome 和 Safari 都是如此。
方案 3 则是一个折中方案,如果 Web 字体能在一段时间内加载完,不会有因为字体变换带来的抖动;同时如果加载字体需要很久,也不至于不显示文本。现阶段 Firefox 采用的这种方案。Firefox 默认等 3 秒,可以找到 about:config 中的 gfx.downloadable_fonts.fallback_delay 配置来修改。
实际上,还有人提出第 1、3 两种方案中,如果字体下载完后只是放入缓存,而不是再次渲染,就可以避免内容抖动。但这样会造成用户连续两次访问同一网页,可能看到不一样的文本渲染效果。到目前为止,没有浏览器采用这种方案。
无论是什么方案,都应该只影响使用了 Web Fonts 的文本渲染,页面上其他元素的渲染不应该受到影响,更不应该停止。但是,在 IE 中,如果 Web Fonts 定义之前有任何 JS 代码,浏览器会停止所有的渲染工作,直到字体下载完成或失败。另外,IE 还会下载页面上定义的全部 Web Fonts 文件,无论是否会被用到。
不知道大家是否遇到过这样的情况:用 Chrome 访问部分网站时,经常图片都加载完了,源代码也是完整的,就是页面上一个字都没有,而 Firefox 没这个问题。看到这里,大家应该都明白了:这很有可能是因为字体文件那个请求迟迟得不到响应造成的。出现这种情况时,点击 Chrome 的停止按钮,通常文字就能出来。原理很简单:手动告诉浏览器不要傻等 Web Fonts 了,马上使用默认字体渲染。更彻底的解决方案是换用稳定可靠的网络来访问这些网站(如:googleusercontent.com)。
转机
虽然以上描述的问题不能完全怪 Chrome,但 Chrome 的做法确实不太合理。通常,使用 Web Fonts 只是为了给用户带来更好的视觉体验,而让用户更快的看到页面内容才应该是优先考虑的。这种为了更好的效果(以及避免内容抖动)而降低可用性的做法,实际上是在伤害用户体验。
下面这个表格,描述了字体大小分布,以及不同比例用户加载字体文件所需时间:
Web 字体大小 | 占比 | 50% | 70% | 90% | 95% | 99% |
---|---|---|---|---|---|---|
0KB - 10KB | 5.47% | 136 ms | 264 ms | 785 ms | 1.44 s | 5.05 s |
10KB - 50KB | 77.55% | 111 ms | 259 ms | 892 ms | 1.69 s | 6.43 s |
50KB - 100KB | 14.00% | 167 ms | 882 ms | 1.31 s | 2.54 s | 9.74 s |
100KB - 1MB | 2.96% | 198 ms | 534 ms | 2.06 s | 4.19 s | 10+ s |
1MB+ | 0.02% | 370 ms | 969 ms | 4.22 s | 9.21 s | 10+ s |
可以看到,大部分字体文件都在 100kb 以下,这时 95% 的用户都能在 3s 内下载完。同时也可以看到,仍然有一部分用户需要很久才能下载完字体,这意味着如果他们用的是 Chrome 或 Safari,很长一段时间内他们看到的页面上很可能没有任何文字。
幸好 Chrome 的开发人员也意识到了这一点,很早就开始了对这个问题的讨论。并且,从 Chrome 35(当前还是 dev 版)开始,Chrome 采用了跟 Firefox 一样的策略:对于使用了 Web Fonts 的文本,如果三秒后字体还没加载完,用默认字体渲染;等字体加载完成,使用新字体再次渲染。对照上面的表格,这个策略十分合理,希望 Safari 也能跟进。
尾声
记得 Web Fonts 这项技术刚出来的时候,大家就讨论过中文 Web 字体面临的难题。相比英文字体几十 kb 的大小,中文字体少说好几 M 的身材很容易让人望而却步。好在聪明的同学们很快发现,我们可以为页面上少量需要特别设计的文字定制字体;我们还可以把 Web Fonts 用在实现网站小图标上。这样,字体文件大小可以得到控制。但本文提到的阻塞 Webkit 渲染文本的问题不容忽视,所以有一些建议供大家参考:
- 不滥用 Web Fonts(任何新技术都不要滥用!);
- 在所有 JS 代码之前定义 Web Fonts(否则在 IE 中,字体文件的加载会阻塞所有界面渲染);
- 不要定义不会被用到的 Web Fonts(IE 会加载它们);
- 常规的静态资源优化手段也要用在 Web Fonts 上(缓存、GZip 等等);
- 对于不同业务用到的相同 Web Fonts,使用同一个地址(类似 JS 公共库托管,同样是为了尽可能利用浏览器缓存),需要特别注意的是:Firefox 下针对非同源字体,需要启用 CORS(通过 Access-Control-Allow-Origin 响应头来控制);
本文链接:https://mailseason.com/post/chrome-and-web-fonts.html,参与评论 »
--EOF--
发表于 2014-03-24 01:57:25,并被添加「Chrome、CSS」标签。查看本文 Markdown 版本 »
专题「浏览器」的其他文章 »
- iOS 10 Safari 视频播放新政策 (Oct 07, 2016)
- Chrome 中 scrollingElement 的变化 (Apr 16, 2016)
- 域名小知识:Public Suffix List (Nov 28, 2015)
- window.opener.location 安全风险讨论 (Oct 09, 2015)
- 使用 SRI 增强 localStorage 代码安全 (Sep 26, 2015)
- Subresource Integrity 介绍 (Sep 23, 2015)
- 移动 Web 与 JavaScript 定时器 (Mar 27, 2014)
- Webkit 异步加载 CSS 的奇怪现象 (Dec 25, 2013)
- 小成本实现部分选中的复选框 (Dec 22, 2013)
- Chrome 滚动条冻结现象 (Dec 02, 2013)
Comments
Waline 评论加载中...