网页字体:使用Webfonts还是本地加载的字体?

115

自从使用 Cufon 后带来的问题,我不再使用外部字体资源,但最近,我一直在寻找替代方法来加载字体,看看是否有更好的方法;更好的方法总是会突然出现。

有很多新方法,似乎每种方法都有变化;我应该使用 typekit?还是使用 Google Web Fonts (带js或css)?我应该继续使用本地加载字体(例如 fontsquirrel.com 生成的方法)吗?

下面我将列出似乎最受欢迎的方法以及一些测试,但是真的值得转向Web字体吗?它似乎会带来更高的资源负载(Http请求),并且具有较少的文件格式类型(兼容性较差)等。但看起来,在大多数情况下,文件是异步和高效加载的。

  1. 这只是情况和需求的问题吗?如果是,它们是什么?
  2. 这些方法之间有明显的区别吗?
  3. 是否存在我未列出的更好的方法?
  4. 性能、外观、依赖关系和兼容性的优缺点是什么?

我真的在寻找最佳实践,性能是很重要的,但可扩展性和易用性也很重要。更不用说外观和感觉了。


Google CSS

  • 只使用外部样式表
  • 只使用最小兼容文件类型
  • 可以使用@import<link>,或将样式表的内容(@font-face)直接放入您自己的样式表中。

测试结果

  78ms load of html
  36ms load of css

Google JS Method

  • 使用webfont.js加载样式表
  • 仅使用最小的兼容文件类型
  • :root元素附加到类
  • 将脚本添加到头部。

测试结果

    171ms load of html
    176ms load of js
    32ms load of css

Typekit方法

  • 添加具有类别的:root元素。
  • 可以使用*.js片段或外部加载的*.js文件。
  • 使用data:font/opentype替代字体文件。
  • 将脚本添加到头部。
  • 将嵌入式CSS添加到头部。
  • 将外部样式表添加到头部。
  • 您可以轻松地从typekit.com中添加/删除/调整字体和目标选择器。

测试结果

  169ms load of html
  213ms load of js
  31ms load of css
  3ms load of data:font/

enter image description here


……和Font Squirrel方法

@font-face{
    font-weight:400;
    font-style:normal;
    font-family:open_sanslight;
    src:url(../font/opensans-light-webfont.eot);
    src:url(../font/opensans-light-webfont.eot?#iefix) format(embedded-opentype),
        url(../font/opensans-light-webfont.woff) format(woff),
        url(../font/opensans-light-webfont.ttf) format(truetype),
        url(../font/opensans-light-webfont.svg#open_sanslight) format(svg)
}

…或使用数据:font方法…

@font-face {
    font-family: 'open_sanslight';
    src: url('opensans-light-webfont-f.eot');
}

@font-face {
    font-family: 'open_sanslight';
    src: url(data:application/x-font-woff;charset=utf-8;base64,d09GRgABAAAAAF4sABMAAAAArXQAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAABGRlRNAAABqAAAABwAAAAcZLn0KkqwK44Jq866WBSpzpsNY2IyGAhoJFBbYjuxmyns5sNa4NwldcJ7eh3Uy5gQkURIlqWzONe3HcLsDX1x/+jifDXvbzgTBjopZElndil3hJkERJkmRJkVRJk3TJkEzJkmzOc4HLXOEOF7nEX/*thisisnotafullencodingjustanexample*/bZwUnK4yS3JlTx2Sr4USKEUSbHVX9fcGNBs4fqgw+GoNHU7lKr36Eqn0lCWt6pHFpWaUlc6lS6loSxRlirLlP/uuU01dVfT7L6gPxyqraluCpgj3WtqeC1V4VBDW2N4K1r1esw/IupKp9L1FwlqnuIAAAB42j3NvQ7BUBjG8R5tTz/0u2UjNTTESYQbMGmXLiISbeI6zBYjbuWtye7CeMJxtuf3LP8ne1+IXbWa7G3TMXZru4qLZkJRW1O2wzi3I+Li2Gik5yXpYkNGXj70YU98YQLGHxwwXxIWwO8SNmAdJBzAXku4gFNI9AF38QMjTwZ9vN6yJzq9OoEB6I8VQzDYK0ZguFKMwWiumIDxTDEFk6liBqaF4gDMFFvKxAfOxFUGAAABUxSL9gAA) format('woff'),
         url('opensans-light-webfont-f.ttf') format('truetype'),
         url('opensans-light-webfont-f.svg#open_sanslight') format('svg');
    font-weight: normal;
    font-style: normal;

}

8
这是一个好问题。 - dachi
2
我不确定这是否是最佳方法,但我总是像这样使用Google CSS <link href='http://fonts.googleapis.com/css?family=Open+Sans:300' rel='stylesheet'> - lefoy
1
这是一篇非常不错的文章,讲述了如何声明防弹 @font-face 声明,或许你可以找到有用的信息。http://www.paulirish.com/2009/bulletproof-font-face-implementation-syntax/ - lefoy
我本来打算再等一天左右,然后自己设置一个。在接受答案之前,我真的很想了解一下Typekit。我的声望有点低,所以如果你愿意做的话,那就请尽管,如果不愿意,那么明天我很可能会自己设置。 - darcher
离题并带有赏金?奇怪的。 - hazzik
显示剩余7条评论
6个回答

39

首先,我来解释一下关于Google提供的一些内容。它会加载您的浏览器能够处理的最小格式。WOFF提供小文件大小,并且您的浏览器支持它,因此您看到的是这种格式。WOFF也相当广泛地得到了支持。但是,在Opera中,您可能会得到字体的TrueType版本。

我认为文件大小逻辑也是Font Squirrel尝试按照那个顺序的原因。但那大多是我的猜测。

如果您在一个每个请求和字节都很重要的环境中工作,您将不得不进行一些分析以找出哪种方法最适合您的用例。人们只会查看一个页面并永远不再访问吗?如果是这样,缓存规则就不太重要。如果他们正在浏览或返回,Google可能比您的服务器拥有更好的缓存规则。延迟是更大的问题还是带宽是更大的问题?如果是延迟,那么请尽量减少请求,所以将其本地托管并尽可能合并文件。如果是带宽,就选择产生最小代码和最小字体格式的选项。

现在,我们来考虑CSS与JS。让我们看看以下HTML片段:

<head>
    <script type="text/javascript" src="script1.js"></script>
    <link rel="stylesheet" type="text/css" href="style1.css" />
    <style type="text/css">
        @import url(style2.css);
    </style>
    <script type="text/javascript">
        (function() {
            var wf = document.createElement('script');
            wf.src = 'script2.js';
            wf.type = 'text/javascript';
            wf.async = 'true';
            var s = document.getElementsByTagName('script')[0];
            s.parentNode.insertBefore(wf, s);
        })();
    </script>
</head>
在很多情况下,script1style1style2会阻塞。这意味着浏览器无法继续显示文档,直到该资源加载完成(尽管现代浏览器会稍微模糊一些)。这实际上可能是一件好事,特别是对于样式表。它可以防止未经样式处理的内容闪烁,并防止应用样式时出现的巨大位移(作为用户,这真的很烦人)。
另一方面,script2不会阻塞。它可以稍后加载,而浏览器可以继续解析和显示文档。所以这也可能有益处。
具体谈论字体(更具体地说,是Google提供的字体),我可能会坚持使用CSS方法(我喜欢@import,因为它将样式与样式表保持在一起,但这可能只是我的个人偏好)。由脚本加载的JS文件(http://ajax.googleapis.com/ajax/libs/webfont/1/webfont.js)比@font-face声明要大,看起来像是更多的工作量。我认为实际的字体本身(WOFF或TTF)加载不会阻塞,因此不应该对速度造成太大影响。我个人不是CDN的铁杆拥护者,但事实是它们真的非常快。Google的服务器将比大多数共享托管计划快得多,由于它们的字体非常受欢迎,人们甚至可能已经缓存了它们。
就这些了。 我没有使用Typekit的经验,所以在我的理论中没有提到它。如果有任何不准确之处,请指出。

我认为这大部分都是情境性的,但你提到阻止加载和FOUT问题确实很有意义。我在这里读了一下:http://www.paulirish.com/2009/fighting-the-font-face-fout/ & http://www.stevesouders.com/blog/2009/10/13/font-face-and-performance/。我会进行一些测试,并在今晚发布性能差异。感谢您提供如此棒的见解。 - darcher

12

我觉得您在提问中已经很好地解决了加载时间的问题。从我的角度来看,有一些应该添加到列表中的其他来源,还有一些其他考虑因素需要被考虑以获得完整的选项视图。


其他可靠字体来源

cloud.typography

http://www.typography.com/cloud/

据我所知,字体以数据形式嵌入到CSS文件中:

@font-face{ 
    font-family: "Font Name"; 
    src: url(data:application/x-font-woff;base64,d09GRk9UVE8AACSCAA0AAAAARKwAAQAAAAAiVAAAAi4AAAadAAAAAAAAAABDRkYgAAAIyAAAFCgAABmIK5m+CkdERUYAABzwAAAAHQAAACAAXQAER1BPUwAAHRAAAAQlAAAYAq+OkMNHU1VC ... ); 
    font-weight:400; font-style:normal; 
} 

以下是我的规格:

94ms load of css from their server
37ms load of css from our server (will vary based on your configuration)
195ms load of data:fonts from our server (will vary based on your configuration)

这里是他们的部署高级描述

Fonts.com

我没有使用过这个服务,但他们是一家非常有实力的字体供应商,他们网站上列出的信息非常令人印象深刻。我没有关于他们确切方法的规格,但这是我知道他们拥有的:

  • 世界上一些最著名的可用字体
  • 一个真正巨大的字体库(超过20,000)
  • 桌面字体下载以制作模型
  • 用于在浏览器中测试Web字体的自定义工具
  • 精细的排版控件和子集化
  • 自托管选项

FontSpring

与FontSquirrel有关联。可以在此购买字体以固定价格。字体文件和附带的CSS将被传送以在您自己的服务器上部署,就像FontSquirrel一样。


扩展规格

关于每种字体服务的优缺点,以下是一些比较:

字体库大小

  • Fonts.com:20,000+
  • FontSpring:1000+
  • FontSquirrel:300+
  • Google:600+
  • Typekit:900+
  • Typography.com(cloud.typography.com):可能300+(35个字族)

价格

  • Fonts.com:每月$20,可获得50万次页面访问
  • FontSpring:按字体变化(字体一次购买)
  • FontSquirrel:免费
  • Google:免费
  • Typekit:每月$4,可获得50万次页面访问
  • Typography.com:每月$12.50,可获得100万次页面访问

字体质量

网络字体的质量可以有很大的差别。这可能包括字形本身、间距或字符集大小等内容。所有这些都决定了字体给人的整体印象。虽然免费选项有一些不错的选择,但它们也有一些质量不高的字体,因此您需要仔细从这些来源中进行选择。

  • Fonts.com: 提供字距、字母间距、连字、备用字符和分数等功能
  • FontSpring: 无
  • FontSquirrel: 无
  • Google: 无
  • Typekit: 无
  • Typography.com: 提供小型大写字母、连字、备用字符、备用数字样式、分数等功能,支持多种字体铸造厂,但仅限于H&FJ字体铸造厂,该铸造厂是世界上最好的铸造厂之一。

字体质量 II:排版艺术

桌面排版有许多细节优化,这在web字体中很难实现。其中一些服务提供了实现这些功能的方法。

  • Fonts.com: 字距、字母间距、连字、备用字符和分数等
  • FontSpring: 无
  • FontSquirrel: 无
  • Google: 无
  • Typekit: 无
  • Typography.com: 提供小型大写字母、连字、备用字符、备用数字样式、分数等功能

浏览器支持

主要取决于每种服务支持的字体格式。主要格式如下:

  • EOT:适用于Internet Explorer(IE 4+)
  • TrueType和OpenType:传统格式(Safari 3.1+,FF 3.5+,Opera 10+)
  • WOFF:Web字体的新标准(FF 3.6+,Chrome 5+)
  • SVG:IOS <4.2

更多信息请参见The @Font-Face Rule And Useful Web Font Tricks

所有这些服务都支持主要的字体格式。对于自托管字体,只要使用正确的语法,就可以得到支持。以下是来自FontSpring的bulletproof syntax的2011年更新:

@font-face {
  font-family: 'MyWebFont';
  src: url('webfont.eot'); /* IE9 Compat Modes */
  src: url('webfont.eot?#iefix') format('embedded-opentype'), /* IE6-IE8 */
       url('webfont.woff') format('woff'), /* Modern Browsers */
       url('webfont.ttf')  format('truetype'), /* Safari, Android, iOS */
       url('webfont.svg#svgFontName') format('svg'); /* Legacy iOS */
  }

性能 I: 下载

根据我的理解,使用上述语法可以让浏览器抓取适合它们的特定格式,因此不会下载无用的字体格式。

付费服务如Fonts.com、Typekit或Typography.com使用方法检测正确的格式,然后以CSS文件中的base64数据形式提供正确的字体格式。

我看到你列出的上述方法在高速互联网用户中的差异很小(似乎少于200毫秒),但对于较慢网络上的设备尤其是未缓存页面,考虑这些差异可能值得一试。

性能 II: 子集

如果你知道你只需要使用某些字符,你可以建立一个只包含子集字符的字体,从而减小下载的大小。

  • Fonts.com: 非常详细的控制
  • FontSpring: 可以通过FontSquirrel 网页字体生成器重新编译为子集
  • FontSquirrel: 可以通过网页字体生成器重新编译为子集
  • Google: 非常详细的控制
  • Typekit: "所有字符"或"默认"选项的有限控制
  • Typography.com: 非常详细的控制

性能 III: 交付

  • Fonts.com: 全球CDN或你自己的服务器
  • FontSpring: 基于你的服务器
  • FontSquirrel: 基于你的服务器
  • Google: 全球超级CDN
  • Typekit: 全球CDN
  • Typography.com: 全球CDN(125,000个服务器)

语言支持

  • Fonts.com: 包括亚洲和中东地区的40种语言
  • FontSpring: 西方语言,取决于字体
  • FontSquirrel: 西方语言,取决于字体
  • Google: 西方语言,取决于字体
  • Typekit: 西方语言,取决于字体
  • Typography.com: 西方语言,取决于字体

测试和实施

  • Fonts.com:非常容易,具有广泛的可定制工具
  • FontSpring: 技术性(自己动手实施)
  • FontSquirrel: 技术性(自己动手实施)
  • Google: 容易
  • Typekit: 容易
  • Typography.com: 易于测试,更改后部署稍微麻烦一些

1
这并没有回答提问者的问题,只是对比了几个 Web 字体。 - stackErr
这是关于每个供应商最详细的信息,感谢您提供的所有信息! - darcher

11

如果您在寻找最佳实践,性能是一个重要因素,但可扩展性和易用性也同样重要。更不用提外观和感觉。

答案就像在网页设计中一样:“这取决于具体情况!”

有一点可以确定的是,我不建议使用JS方法(如你第二个示例中所示)。

就我个人而言,我不喜欢让呈现层和CSS样式依赖于Javascript,尽管绝大多数用户已启用它。这是不能混淆的问题。

正如您在给出的示例中所看到的那样,存在某种未经样式修饰的内容快闪烁(FOUC),因为页面在字体可用之前已由浏览器呈现。一旦它可用,页面就会重新绘制。并且站点越大,(性能)影响就越大!

因此,我永远不会使用任何JS解决方案来嵌入字体。

现在让我们看看纯CSS的方法。
从相当长的时间以来一直在讨论“ vs. @import”。个人而言,我喜欢避免使用@import,而始终只使用<link>。但这主要是个人偏好的问题。您绝不能做的一件事情确实是将它们混合使用!

本地 vs. CDN
在决定是否将字体文件托管到本地或使用CDN时,我认为主要取决于要嵌入的不同字体数量和相应字体。

为什么这很重要或者说很关键?
从性能角度考虑,我建议将字体以Base64编码的形式包含在您的(一个)样式表中。但只有.woff格式的文件,因为几乎所有现代浏览器都使用它,这对于大多数访问者来说都是如此。对于其他用户,请接受附加请求。

但由于Base64编码的“开销”和字体文件的大小(即使是.woff格式),如果您没有超过3或4种不同的字体,则应仅使用此技术。并始终确保您的服务器以gzip方式提供(CSS)文件。

这样做的最大优点是您没有为字体文件发出其他请求。并且在第一次页面加载之后(无论您的站点中的哪个页面),CSS文件都被缓存。如果您使用HTML5应用程序高速缓存(您肯定会这样做),这也是一个优势。

除了作者不应在其网站上使用超过3或4种不同字体的事实外,让我们看一下使用Google的CDN的方法。

首先,请注意,您可以(并且始终应该)将所有所需字体包含在一个单独的<link>中,如下所示:

<link href='http://fonts.googleapis.com/css?family=PT+Serif:400,700,400italic,700italic|PT+Sans:400,700,400italic,700italic|Montez' rel='stylesheet' type='text/css'>
这将导致以下响应:
@font-face {
  font-family: 'Montez';
  font-style: normal;
  font-weight: 400;
  src: local('Montez'), local('Montez-Regular'), url(http://themes.googleusercontent.com/static/fonts/montez/v4/Zfcl-OLECD6-4EcdWMp-Tw.woff) format('woff');
}
@font-face {
  font-family: 'PT Sans';
  font-style: normal;
  font-weight: 400;
  src: local('PT Sans'), local('PTSans-Regular'), url(http://themes.googleusercontent.com/static/fonts/ptsans/v6/LKf8nhXsWg5ybwEGXk8UBQ.woff) format('woff');
}
@font-face {
  font-family: 'PT Sans';
  font-style: normal;
  font-weight: 700;
  src: local('PT Sans Bold'), local('PTSans-Bold'), url(http://themes.googleusercontent.com/static/fonts/ptsans/v6/0XxGQsSc1g4rdRdjJKZrNBsxEYwM7FgeyaSgU71cLG0.woff) format('woff');
}
@font-face {
  font-family: 'PT Sans';
  font-style: italic;
  font-weight: 400;
  src: local('PT Sans Italic'), local('PTSans-Italic'), url(http://themes.googleusercontent.com/static/fonts/ptsans/v6/PIPMHY90P7jtyjpXuZ2cLD8E0i7KZn-EPnyo3HZu7kw.woff) format('woff');
}
@font-face {
  font-family: 'PT Sans';
  font-style: italic;
  font-weight: 700;
  src: local('PT Sans Bold Italic'), local('PTSans-BoldItalic'), url(http://themes.googleusercontent.com/static/fonts/ptsans/v6/lILlYDvubYemzYzN7GbLkHhCUOGz7vYGh680lGh-uXM.woff) format('woff');
}
@font-face {
  font-family: 'PT Serif';
  font-style: normal;
  font-weight: 400;
  src: local('PT Serif'), local('PTSerif-Regular'), url(http://themes.googleusercontent.com/static/fonts/ptserif/v6/sDRi4fY9bOiJUbgq53yZCfesZW2xOQ-xsNqO47m55DA.woff) format('woff');
}
@font-face {
  font-family: 'PT Serif';
  font-style: normal;
  font-weight: 700;
  src: local('PT Serif Bold'), local('PTSerif-Bold'), url(http://themes.googleusercontent.com/static/fonts/ptserif/v6/QABk9IxT-LFTJ_dQzv7xpIbN6UDyHWBl620a-IRfuBk.woff) format('woff');
}
@font-face {
  font-family: 'PT Serif';
  font-style: italic;
  font-weight: 400;
  src: local('PT Serif Italic'), local('PTSerif-Italic'), url(http://themes.googleusercontent.com/static/fonts/ptserif/v6/03aPdn7fFF3H6ngCgAlQzBsxEYwM7FgeyaSgU71cLG0.woff) format('woff');
}
@font-face {
  font-family: 'PT Serif';
  font-style: italic;
  font-weight: 700;
  src: local('PT Serif Bold Italic'), local('PTSerif-BoldItalic'), url(http://themes.googleusercontent.com/static/fonts/ptserif/v6/Foydq9xJp--nfYIx2TBz9QFhaRv2pGgT5Kf0An0s4MM.woff) format('woff');
}

正如您所看到的,有9个不同的字体文件,这意味着如果用户本地没有安装其中一个或多个请求的字体,则总共有10个请求(包括链接元素的请求),并且每个新页面请求都会重复这些请求(尽管不传输更多数据)!此外,对于的请求响应永远不会被缓存。

建议:
最终我真的建议将字体文件以.woff格式Base64编码包含在您的样式表中!

请参阅此精美文章,了解如何执行此操作的示例和说明!


非常感谢,一直在寻找这个解决方案! - ken

3
我使用内联CSS方法,因为多余请求的开销比使用BASE64编码时增加的大小还要大。此外,服务器对CSS文件进行Gzip压缩也进一步抵消了这个开销。
另一个选择是异步加载字体,但大多数用户加载后仍然会看到字体“弹出”。
无论使用哪种方法,您都可以通过仅包含您将使用的字符集来减小字体文件的大小。

在使用HTTP2时,没有提到任何额外的开销。 - Chris Gunawardena

1

个人而言,我使用Google Fonts。它们提供了许多不错的选择,并且最近还通过采用Zopfli压缩技术 改进了字体的压缩。Google致力于使网络更快,所以我想他们会在这方面做更多的优化。

无论您选择何种外部字体交付方式,获取字体的请求始终会减慢速度。从速度的角度来看,最好的方法是自己提供字体服务。如果您不介意从外部交付中加载需要的额外毫秒数并认为使用这些服务很容易,那么您应该选择这个方法。

我不知道Typekit和其他服务商,但是在Google Fonts中,您可以选择特定的子集和字符范围以进一步加快交付速度。

选择子集:

<link href="http://fonts.googleapis.com/css?family=Open+Sans&subset=latin" rel="stylesheet">

选择一定范围的字符:
<!-- Only serve H,W,e,l,o,r and d -->
<link href="http://fonts.googleapis.com/css?family=Open+Sans&text=HelloWorld" rel="stylesheet">

你可以使用 dns-prefetch 来进一步提高字体传递的速度。
我认为,也希望Google尽其所能加快字体传递的速度。它加载所需的毫秒数并不会损害我的网站,因此我很乐意使用它们。
长话短说:
如果字体传递所需的毫秒数正在损害您的网站,例如使其加载超过推荐的1秒钟,我认为您应该自己托管它们。

1
关于<link rel=dns-prefetch href='//fonts.googleapis.com'>的观点很好,我用它来进行分析、热图和子域名,但由于某些原因,它没有注册为外部Web字体运行。而且不同字体的加载时间差别很大,我想如果你使用的是相当流行的字体(可能已被缓存)或者只选择了一小部分字体,使用Web字体是一个非常快速的字体来源。我很快就会在这里发布速度测试结果。 - darcher

1
最佳选择是使用ajax导入字体,就像这样:
<script>
    (function() {
        var font = document.createElement('link'); 
        font.type = 'text/css'; 
        font.rel = 'stylesheet';
        font.href = '/url/to/font.css';
        var s = document.getElementsByTagName('link')[0]; 
        s.parentNode.insertBefore(font, s);
      })();
</script>

我在我的网页上这样做,在Google Insights测试中得分提高了9分。

有趣。我得研究一下用这种方法的PageSpeeds。 - darcher
3
async 属性怎么样?它的作用是相同的。 - Tymek

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接