字体加载策略全面指南

本文讲的是字体加载策略全面指南,


2016 年 7 月 12 日, 本文需要 20 分钟的阅读时间。

这份指南并不是教你怎么使用显示图标字体,它有不同的加载优先顺序和使用场景。事实上,此时使用 SVG 或许才是一个长久之计。

跳转到:

快速指南

我想要一个这样的实现途径:

  • 是一个对大多数使用场景来说足够好且全面的实现方式: (例如) 有分类的 FOUT
  • 是尽可能最容易实现的方式: 我已经学习了很多有关 在线字体 (的知识),在我写这篇文章的时候,目前的浏览器还缺少对在线字体高效,稳定和最容易的实现方案。不得不承认,如果你正在寻找现存的可行方案,请考虑 不要使用在线字体。如果你都不清楚在线字体能为你的设计带来什么提升的话,他们确实一点儿都不适合你。别误会,在线字体是一个伟大发明。但是你得让自己明白什么是它能带来的好处。( 由Robin Rendel创作的,为在线字体辩护,论_在线字体的价值_ 是一个让你初步了解在线字体的好文章. 如果你还知道其他的, 请留言告诉我.)
  • 是一个有最佳性能的实现方式: 使用 严格的 FOFT 实现方式其中的一个。就个人而言,在我写作的时候,我个人偏爱 有数据 URI 的严格 FOFT, 但是仍转向了 有预加载 preload 的严格FOFT,因为越来越多的浏览器支持preload(预加载)功能。
  • 能和大量的在线字体(库)很好的配合工作: 如果你痴迷于在线字体(任何多过 4 或 5 个的在线字体或者总共文件大小多于 100KB)这有点复杂。我先推荐你尝试削减你的在线字体的使用量,但如果这不可能保持标准 两个阶段渲染的 FOFT,或 FOUT 的实现方式。为每一个字型使用不同的 FOFT 实现方式(RomanBoldItalic 等等分类)。
  • 将能和我现存的云/在线字体的托管服务解决方案配合使用FOFT 的实现方式一般来说需要亲自托管服务, 所以保持可靠和真的 有分类的 FOUT 的实现方式.

标准

  1. 简化实现: 有时候, 简单才能赶上最后的时间期限。
  2. 渲染性能: FOUT 的特性是允许立刻渲染回退方案的字体也可以渲染在线字体,当它完成加载时。我们可以采用额外的步骤减少大量的显示回退方案字体的时间并且减少了对 FOUT 的影响, 更有甚者能将他们一起消除。
  3. 可扩展性: 一些加载字体的实现方式支持连续的加载在线字体。我们想并行的执行这些请求。我们将评估每一个实现和扩张,发展中的在线字体配合度有多好。
  4. 拥抱未来: 如果有一个新的字体出现它将需要额外的研发和维护么, 或者它将能方便的适配么?
  5. 浏览器支持: 它是否能成功支持足够多的浏览器满足项目上的需要?
  6. 灵活性: 这个实现方式是否容易地促进整合在线字体的请求,重新绘制和(页面)回流? 我们想(完全)控制哪个字体何时(何地)被加载。
  7. 稳定性: 如果一个在线字体的请求被挂起了会发生什么呢?(需要被渲染的)文本将依旧被(显示)可读或者这个在线字体将是一个单点故障(SPOF)(导致整个字体渲染失败)?
  8. 托管服务: 这个实现方式是否需要亲自(虚拟主机)托管服务或者它是否能自适应配合多种多样的字体加载器(由其他云服务商/字体创始人提供)。
  9. 阉割版(裁剪版): 一些字体的(使用)许可证不允许(内容被)裁剪(需要保证完整性),然而有些实现方式不得不为了性能需要对字体(库)进行裁剪。

(Unceremonious) 随意使用 @font-face

随意把@font-face代码块放置在你的网页中并且希望这是最好的办法. 这是 Google Fonts 推荐的默认方式.

优点

  • 非常简单: 增加一个有 WOFF 和 WOFF2 格式的 CSS @font-face 代码块(也可以是 OpenType 格式, 如果你想要 Android 4.4 以下支持 - 比较下 WOFF 和 TTF/OTF)。
  • 拥抱未来: 这是浏览器默认的作法。这就是在线字体的主流形式。只需要在你的 @font-face 中, 在 src 属性中用逗号分割开其他需要包含的 URL , 就能增加额外的字体样式。
  • 在 IE 和 Edge (微软浏览器)上都有上佳的渲染性能: 没有 FOIT,没有被隐藏和不可见的文本。我完全支持微软这个英明的决定。
  • 不需要修改字体(通过裁剪或者其他形式)。 无需担心许可。

缺点

  • 在其他浏览器的渲染性能差强人意: 在多数其他流行的浏览器上最多有 3 秒时间的 FOIT, 切换到 FOUT 加载时间更长. 当然这些请求可能被更早完成, 尽管我们知道互联网(的响应时间)是会变得多么不可靠-但是对于内容至少 3 秒无法阅读, 这个时间还是太长了。
  • 目前来说, 不是很稳定: 一些基于 WebKit 内核实现的浏览器没有一个最大 FOIT 超时时间(虽然 WebKit 最近修复了这个问题并且我相信这个修复会被 Safari Version 10 采用。),这也意味着在线字体的请求会成为一个单点失败(如果这个请求被挂起, 那么内容将永远不会被显示)。
  • 将请求或重绘整合在一起一点都不容易。每一个在线字体都会引发一个单独的重绘/回流步骤和自己的 FOIT / FOUT 超时时间. 这会带来不良的情况, 例如 Mitt Romney 的在线字体问题 ).

结论: 不要使用。

font-display

在你的 @font-face 代码块中增加一个新的 font-display: swap 描述符选择性加入支持 FOUT 的浏览器。另外, 如果考虑到在线字体不是你设计一定需要的, 可以使用 font-display: fallback font-display: optional。在我写这篇文章时, 这个特性还没法在任何稳定的浏览器上使用。

优点

  • 非常简单: 只需要在你的 @font-face 代码块中增加一条 CSS 描述符号。
  • 上佳的渲染性能: 如果这个实现方式能被大部分的浏览器支持, 这将给我们一个没有任何JavaScript的 FOUT。 一个只有 CSS 的实现方式会更理想。
  • 超棒的拥抱(面向)未来: 与子线字体样式成正交状态。不需要改变什么, 你就可以在栈上增加新的字体。
  • 非常稳定: 即使在线字体的请求被挂起, 一种 FOUT 实现方式也将在浏览器中显示支持回退方案的文本。更好的是-你的在线字体并不依赖 JavaScript ployfill, 这意味着如果 JavaScript 方法失败, 用户依旧还能看到在线字体。
  • 不需要修改字体(通过裁剪或者其他形式)。无需担心许可.

缺点

  • 没有稳定的浏览器支持。只有 Chrome平台有一个更新状态。它没有被录入 Firefox 或者 Edge 平台。开发者门将可能需要匹配 JavcScript 实现方式, 直到一流的浏览器能支持。
  • 有限的灵活性: 没法整合请求和重绘。这也并没有听上去那么糟-如果你 FOUT 所有的东西你将避免发生 Mitt Romney 的在线字体问题, 但是整合在其他方面会很有用-我们将在之后讨论。
  • 托管服务: 没法在任何已知的在线字体托管服务中控制这个属性。这不在谷歌字体 CSS 中, 举例来说. 当浏览器支持以后, 这将会被改变。

结论: 但加无妨,但还是不够。

预加载 preload

增加 <link rel="preload" href="font.woff2" as="font" type="font/woff2" crossorigin> 更快的获取到你的字体。配合@font-face 代码块使用并且也可以和 font-display 描述符号一起锦上添花。

切记: 这个实现方式的利弊完全取决于配合使用的加载策略, 无论是 随意使用 @font-face 或者 font-display

优点

  • 一键实现, 只需要一个 <link>
  • 比 @font-face 代码块更好的渲染性能,在线字体的请求优先级很高。
  • 拥抱未来, 如果你使用 type 属性去指定字体样式。在 WOFF2 之前, 一个网页浏览器扔可能执行 preload (虽然听上去不太会), 并且如果没有这个属性, 你可能会看到一个多余的请求。所以, 清确保包含了 type
  • 不需要修改字体(通过裁剪或者其他形式)。无需担心许可。

缺点

  • 可扩展性: 预加载的内容越多, 初始化渲染的内容就越容易被阻塞(注意, 从网站上获取的比对数据都使用了严格的 CSS)。 尝试仅仅使用 1 到 2 个重要的在线字体。
  • 有限的游览器支持 - 目前只有 Blink 支持, 但会越来越多。
  • 灵活性: 没法整合重绘/回流。
  • 这个实现方式你没法使用第三方的托管服务. 你需要在标记阶段提交你所请求的在线字体的 URL。 Google Fonts , 在 CSS 向他们的 CDN 请求的时候生成这些。

结论: 没有使用的必要。

不要使用在线字体

好吧, 其实我并不想讨论太多这个, 实际上这根本就不是一个技术上的加载策略。_但我必须说这比起滥用在线字体要好的多。_你正在错过很多在线字体能带给你新的字体特性和提升阅读性(的机会), 但这是你的选择。

优点

  • 不太确定哪个更加容易: 仅使用没有 @font-face 的 font-family
  • 几乎是即刻渲染: 不用担心 FOUT 或 FOIT

缺点

  • 可适用性很少。仅仅有少部分的字体支持跨平台。可查看 fontfamily.io 确认某个满足你需求的系统字体是否能被浏览器接受(支持)。

结论: 当然,可以使用。但我一点儿都不意外。

内嵌数据 URI

这个方法有两种嵌入式(的代码块): 一个是 <link rel="stylesheet"> 请求或在 <style> 在服务器渲染标记语言中。alibaba.com (在 CSS 请求中有两个在线字体)和 medium.com (7个在线字体)都使用了这个实现方式。

优点

  • 超棒的渲染性能: 没有 FOUT 或者 FOIT。 太了不起了!
  • 灵活性: 因为没有 FOUT 或 FOIT , 所以也就不必担心重绘和回流了。
  • 稳定性: 那些内嵌的代码将所有的事情放在了服务器初始化的请求中。

缺点

  • 一些渲染性能的缺陷: 虽然这个实现方式没有 FOUT ,但它将大大延迟初始化渲染的时间, 另一方面, 它将会"完成"渲染。但牢记即使是一个单独的 WOFF2 在线字体都差不多 10KB-15KB, 内嵌式只是一个数据 URI , 它将在严格的渲染过程中花费( HTTP/1 推荐值) 14KB 左右。
  • 浏览器支持: 没有利用在 @font-face 代码块中使用的以逗号分隔样式的列表: 这个实现方式仅内嵌一个样式类型。通常来说这就是 WOFF , 所以使用这个方法迫使你选择更有普遍性的 WOFF 或者更加少的支持但是更小的文件 WOFF2
  • 可扩展性差: 请求无法并行执行。只能逐条加载。
  • 亲自托管服务: 当然是必需!

结论: 仅在你无法容忍 FOUT 时使用该方法. 我个人不推荐用这个.

异步数据 URI 样式表

使用类似 loadCSS 的工具获取样式表, 所有的字体都嵌入在数据 URI 中。你也将竟然看到这个配合一个本地存储方法来把这个样式表存储在用户本地供其他视图重复使用。

优点

  • 渲染性能: 几乎可以消除FOIT (详见缺点)。
  • 灵活性: 方便的将请求整合到一个单独的重绘中(将多个数据 URI 放入到一个样式表)。
  • 容易性: 不需要其他额外的 CSS 的修改. 这是一个大大的好处, 然而, 实现的过程并不只有好处。
  • 稳定性: 如果异步请求失败了, 回退策略文本也将会被显示。

缺点

  • 渲染性能: 能被注意到, 但是非常短的 FOIT , 当样式表和数据 URI 被解析的时候。这有点碍事, 我都不用看源码都知道这个实现方式被使用了。
  • 灵活性和可扩展性: 整合的请求和重绘被结合在一起了。如果你也整合了多个数据 URI 到一起(这样造成都是顺序加载而非平行), 他们也将一起被重绘。通过这个方法, 你不可能再并行加载并且整合重绘。
  • 不太好维护. 你必须决定你支持哪些样式的字体。在获取数据 URI 数据样式表之前, 你的 JavaScripter 加载器将需要决定那种字体样式被支持(WOFF2 / WOFF). 如果有一个新的字体样式出现, 你将必须再为这个特性测试是否可行。
  • 浏览器支持(情况): 你可以采用硬编码 WOFF2/WOFF 去绕开加载器的持续维护工作, 但这势必引发更多的不需要的请求(相同的缺点我们已经在嵌入式数据 URI讨论过)。
  • 亲自托管服务: 必须。

结论: 这个可以,但是我们能做的更好。

有分类的 FOUT

使用 CSS 字体库中的加载API函数(polyfill)去检测当有某一个字体被加载时, 只将这个成功加载的在线字体应用到你的 CSS 中。同行这意味着放置一个开关类在你的 <span><html></span> 元素上。使用 SASS/LESS 进行更简单的维护操作。

优点

  • 渲染性能: 消除 FOIT。这个方法已经经过尝试和测试了。它也是 TypeKit推荐的一个实现方式.
  • 灵活性: 方便整个请求到一个重绘(可使用一个类处理多个在线字体的加载)。
  • 可扩展性: 并行执行请求。
  • 稳定性: 如果请求失败, 回退策略的文本也能被显示。
  • 托管服务: 可独立字体加载器功能(方便实现第三方的托管服务或现存的 @font-face 代码块)。
  • 最多的浏览器支持, polyfills 几乎能被所有的在线字体支持。
  • 拥抱未来: polyfills 并不一定和字体样式耦合, 它也能和现存的 @font-face 代码块工作。也就是当有一个心的样式出现, 你只需要一如既往的改变你的 @font-face 就可。
  • 不需要修改字体(通过裁剪或者其他形式). 无需担心许可。

缺点

  • 需要严格的维护和控制你的 CSS (代码). 单独使用在线字体集,且没有受保护的加载类, 可能会触发 FOIT
  • 一般都需要你硬编码(选择)哪个在线字体是你想要加载在网页上的。你需要加载多过一个网页需要的在线字体. 新的浏览器只会现在当前页面所需要的在线字体 @font-face 的实现方式。这就是为什么 纽约时报在他们的主页上侥幸逃过 100 个不同的 @font-face 代码块 - 浏览器只会下载一小部分。 通过这个方法, 你必须告诉浏览器哪个字体需要被下载, 与使用无关。

结论: 这是标准线. 被大部分情况使用。

两个阶段渲染的 FOFT, 或 FOUT

该实现基于 有分类的 FOUT 方法, 当你要对同一个字型加载不同的字体粗细和样的时候是非常有用的, 比如, Roman , Bold ,Italic , Bold Italic , BookHeavy 等等。 我们可以将在线字体分为两个阶段: Roman 优先, 之后将立即渲染faux-boldfaux-italic的内容( 使用字体合成), 然后真实的在线字体, 大权重和加载其他样式。

优点

  • 所有 有分类的 FOUT 方式的优点。
  • 渲染性能: 极大减少了当在线字体加载完成后内容发生的跳跃。考虑到我们把在线字体的加载分成两个阶段, 这允许第一步(Roman 字体 - 引发回流最多的)比我们把所有的字体整合到一个重绘更快。

缺点

  • 所有 有分类的 FOUT 存在的缺点。
  • 一些设计者讨厌字体合成. 客观来说, 合成的变化没有他们对应的有作用. 但这不是一个公平的比较. 牢记合成的版本知识一个临时性的替代物, 我们要问的是, 或多或少比回退策略的字体来的有用么? 答案是更多!

严格的 FOFT

这个方法和标准的 FOFT 实现方式不同的是, 在第一阶段不是完全的 Roman 在线字体, 我们使用 Roman 在线字体的一个子集(通常只会包含 A - Z 和 0 - 9 或标点符号)。 完全的 Roman 在线字体在第二阶段加载不同的权重和样式。

优点

  • 所有 FOFT 现存的优点。
  • 渲染性能: 第一阶段甚至加载的更快(特别在更慢的网络上更显著)更减少了第一阶段在线字体重绘的时间, 让你使用最多的在线字体更快的产生。

缺点

  • 所有 FOFT 现存的缺点。
  • 会引入少量的开支, 在第一阶段加载的 Roman 字体的子集会被重复在第二阶段完整的 Roman 字体时再加载一次. 这就是为了最小化回流的代价。
  • 许可证限制: 需要裁剪。

结论: 可以使用以下加强过的 严格的 FOFT 的变种。

有数据 URI 的严格 FOFT

这个不同的 FOFT 实现方式可以通过第一阶段加载的内容来改变机制。我们可以简单的以直接嵌入数据 URI 到标记语言的形式, 嵌入在线字体, 而不是使用一般的 JavaScript API 来初始化一个下载, 加载字体。就如之前讨论的, 这样会阻塞初始化渲染, 但是由于我们仅嵌入一小部分的子 Roman 在线字体, 对于完全消除FOUT, 这点代价还是值得的。

优点

  • 所有 严格的 FOFT 现存的优点.
  • 消除了 FOIT 并且对 Roman 字体极大地减少 FOUT。对在第二阶段加载的额外字体会发生一个小的回流并且当其他权重和样式被加载时, 但这个影响很小。

缺点

  • 所有 严格的 FOFT 现存的缺点。
  • 这个小的内联数据 URI 将少量的阻塞初始渲染. 我们用它交换 FOUT 大大的减少。
  • 亲自服务托管: 必须。

结论: 就我来看, 这就是目前的黄金标准。

有预加载 preload 的 严格 FOFT

这个不同的 FOFT 实现方式可以通过第一阶段加载的内容来改变机制。我们使用新的 preload 在线标准, 而不是使用一般的JavaScript API 来初始化一个下载, 加载字体。在之前已经介绍过 preload方法, 这会比之前更快的触发下载。

优点

  • 所有 严格的 FOFT 现存的优点。
  • 渲染性能: 下载应该比之前的方法早被触发。 我猜测这个甚至比 HTTP 的报头更戏剧性, 但还并没有证实我的预感. 这个方法比 有数据 URI 的严格 FOFT 更好, 他能使用浏览器的缓存重复(发送)请求, 而不是重复发送一样的在线字体, 与每一个服务器标记(语言)请求。

缺点

  • 所有 严格的 FOFT 现存的缺点。
  • 只使用一个在线字体样式。
  • 如上述所陈述的, 浏览器的支持有限 在我写这篇文章时, 只有 Blink 支持。
  • preload 会少量的增加初始化渲染的延迟(注意对比的数据由严格 CSS 的网站生成)。
  • 亲自托管: 可能需要。

结论: 当浏览器能更好的支持的时候,这会是新的黄金标准。






原文发布时间为:2016年07月28日


本文来自合作伙伴掘金,了解相关信息可以关注掘金网站。

时间: 2024-10-31 19:28:47

字体加载策略全面指南的相关文章

网页端字体加载优化

本文讲的是网页端字体加载优化, 网络字体加载看起来也许非常复杂,但如果你使用本文的字体加载模式的话,这也并不是一件复杂的事情.你可以将这些模式组合起来,创建一个兼容所有浏览器的字体加载方式. 这些模式的代码样例都使用了 Font Face Observer,一个精简的网络字体加载器.Font Face Observer 将会根据浏览器的兼容情况使用最高效的方式来加载字体,所以这是一个非常棒的网络字体加载方式,同时你不需要为跨浏览器的兼容性而操心. 基础字体加载模式 分组字体加载模式 限制字体加载

Spring中的资源加载策略

文/杜琪(简书作者) 原文链接:http://www.jianshu.com/p/9cdd6d750216 著作权归作者所有,转载请联系作者获得授权,并标注"简书作者". 本文是阅读<Spring揭秘>的笔记 资源表示:ResourceSpring框架内部使用org.springframework.core.io.Resouce接口作为所有资源的抽象和访问接口. //Resource接口的定义 public interface Resource extends InputS

字体加载-求救大牛!Android开发用兰亭黑后加载变慢~~~~

问题描述 求救大牛!Android开发用兰亭黑后加载变慢~~~~ 我们在开发一个app,用的是兰亭黑,没有用原生态的.但用指定字体后页面加载和频道切换特别慢,研究了半天找不到问题.换回系统自带字体就OK...求大神指点!!!跪谢~ 解决方案 换一种类似的字体看看呢. 解决方案二: 你可以首先把字体加载到内存当中!不要等到设置字体的时候再去加载-试试看- 解决方案三: 建议用手机自带的字体

高性能Javascript--脚本的无阻塞加载策略

Javascript在浏览器中的性能,可以说是前端开发者所要面对的最重要的可用性问题. 在Yahoo的Yslow23条规则当中,其中一条是将JS放在底部 .原因是,事实上,大多数浏览器使用单进程处理UI和更新Javascript运行等多个任务,而同一时间只能有一个任务被执行.Javascript运行了多长时间,那么在浏览器空闲下来响应用户交互之前的等待时间就有多长. 从基本层面说,这意味着<script>标签的出现使整个页面因脚本解析.运行而出现等待.不论实际的 JavaScript 代码是内

AndroidStudio 实现加载字体资源的方法_Android

AndroidStudio 实现加载字体资源的方法 在android中字体的格式总是不能尽善尽美的显示出来 ,  于是要求我们使用一些有美感的字体,加载的方式(就像HTML的字体一样),我们需要通过加载字体的方式来使用android中不曾提供的字体; 首先在androidstudio中找到assets文件夹 , (位于serc/main/java下,与res在同一个文件里面) , 找到之后将字体文件(*.ttf)放入这个文件夹下(当然为了规范起见,我们可以再asseets下建立一个font文件夹

AndroidStudio 实现加载字体资源的方法

AndroidStudio 实现加载字体资源的方法 在android中字体的格式总是不能尽善尽美的显示出来 ,  于是要求我们使用一些有美感的字体,加载的方式(就像HTML的字体一样),我们需要通过加载字体的方式来使用android中不曾提供的字体; 首先在androidstudio中找到assets文件夹 , (位于serc/main/java下,与res在同一个文件里面) , 找到之后将字体文件(*.ttf)放入这个文件夹下(当然为了规范起见,我们可以再asseets下建立一个font文件夹

SWF关于远程源和允许跨域数据加载

加载|数据 与 HTML 页面类似,SWF 文件是用于捕获和显示信息的窗口.然而,SWF 文件可以在浏览器中保持加载状态,同时用新信息持续更新而不必重新加载整个页面.使用动作脚本函数和方法,可以向服务器端脚本.文本文件以及 XML 文件发送信息,也可从它们那里接收信息. 此外,服务器端脚本可从数据库中请求特定信息,然后将其转发给 SWF 文件.可用多种不同的语言撰写服务器端脚本:其中最常用的是 CFML.Perl.ASP (Microsoft Active Server Pages) 和 PHP

在浏览器加载CSS 时防止影响页面渲染的方法

  本文展示了一种技术,它能通过异步下载样式表,以阻止它们的下载阻塞页面的渲染,从而尽可能快的让访问者获取到信息内容. 警告! 我发这篇帖子全是好意,但是它并不负责让读它的人意识到下面将会遇到的问题. 社区很快地给了我许多的反馈 (有些反馈我很感激) ,而越来越明显的是这项技术并不如我所希望的那样稳定. 不像我那样的成功地对它进行了测试和利用,许多开发者在 IE 和 Firefox 中都遇到了问题( F F测试版中直接崩溃) 而其他人则报告在 Chrome 和 Safari 中是成功的.我现在的

无线性能优化:页面可见时间与异步加载

如何让页面尽可能早地渲染页面,页面更早可见,让白屏时间更短,尤其是无线环境下,一直是性能优化的话题. 页面可见时间 页面可见要经历以下过程: 解析 HTML 为 DOM,解析 CSS 为 CSSOM(CSS Object Model) 将 DOM 和 CSSOM 合成一棵渲染树(render tree) 完成渲染树的布局(layout) 将渲染树绘制到屏幕 layout 由于 JS 可能随时会改变 DOM 和 CSSOM,当页面中有大量的 JS 想立刻执行时,浏览器下载并执行,直到完成 CSSO