在不使用Font Face Observer的情况下异步或延迟加载Google字体的方法

49
我想在我的网站上使用谷歌字体"Noto Serif",但是当我使用Google PageSpeed Insights测试它时,除了一个问题之外,它说一切都很完美:

<link href="https://fonts.googleapis.com/css?family=Noto+Serif" rel="stylesheet">

该问题是: 你的页面有1个阻塞CSS资源。 这会导致渲染页面时延迟。 在等待以下资源加载完成之前,无法呈现页面上的任何以上折叠内容。请尝试推迟或异步加载阻止资源,或直接在HTML中内联这些资源的关键部分。 我知道有一个解决方法,就是在HTML文件底部使用 <script> 链接字体。但这种解决方法的问题是每次单击我的网站中的某些东西时都会导致闪烁的未样式化文本。我正在使用Jekyll托管GitHub Pages,所以我不认为我能安装Font Face Observer :(

请出于显而易见的原因使用localfont.com... - Mr. Hugo
7个回答

23

您可以使用此脚本异步加载网络字体:

<script>
   WebFontConfig = {
      typekit: { id: 'xxxxxx' }
   };

   (function(d) {
      var wf = d.createElement('script'), s = d.scripts[0];
      wf.src = 'https://ajax.googleapis.com/ajax/libs/webfont/1.6.26/webfont.js';
      wf.async = true;
      s.parentNode.insertBefore(wf, s);
   })(document);
</script>

你需要 这个库,它非常容易实现。我是最近学习的课程 - 响应式 Web 设计基础中学到的,如果你感兴趣可以在这里查看。


6
这个库(webfontloader)似乎不再维护。此外,一些人在IE和Edge上使用起来会出现问题。我对使用它表示疑虑。 - szymond
谢谢提醒和修改,我已经有一年没用它了。 - Mirza Sisic
3
请记住,当JavaScript被禁用时,这将防止字体加载。 - Neurotransmitter
1
@神经递质 同意。最好在原始的“link”标签中放置一个“noscript”标签。这样当JS被禁用时,字体就会像正常加载一样。 - Jongwoo Lee

20

基于这个预加载样式表的策略:

<link rel="preload" 
      href="https://fonts..."
      as="style"
      onload="this.onload=null; this.rel='stylesheet'; document.body.classList.add('fontLoaded')">
body {
  font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;
}

body.fontLoaded {
  font-family: 'GOOGLE FONT', 'Helvetica Neue', Helvetica, Arial, sans-serif;
}

你认为谷歌字体 API 提供的该字体对换行显示类型有影响吗? 谷歌字体为 Roboto 字体提供此 URL:https://fonts.googleapis.com/css2?family=Roboto:wght@400&display=swap - Lucas Vazquez
2
@pavlo 请注意,这还没有完全支持,样式不会在所有地方加载:https://caniuse.com/#search=preload - retrovertigo
1
请查看 https://walterebert.com/playground/css/async/。 - Raffi

5

将两个属性添加到你的代码中。一个是 rel="preload",另一个是 as="style"。最终代码应如下所示:

<link href="https://fonts.googleapis.com/css?family=Noto+Serif" rel="stylesheet" rel="preload" as="style">

据我所知,这个不起作用。如果您有重复的“rel”属性,则最后一个将“覆盖”前面的属性,因此rel =“preload”将被忽略。您需要仅拥有rel =“preload”,然后在加载后将其切换为rel =“stylesheet”,就像我刚刚添加的这个答案一样。 - joe

2
非常简单的方法:
<link rel="preload" href="styles.css" as="style" onload="this.onload=null;this.rel='stylesheet'">

只需用您的字体URL替换styles.css。它会加载字体,然后一旦完成(onload),通过将rel属性切换为stylesheet来“启用”它。

更多细节请参见这里


0

有人尝试过这个解决方案吗?

<!-- other <head> stuff -->

<!-- connect to domain of font files -->
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>

<!-- optionally increase loading priority -->
<link rel="preload" as="style" href="(font CSS URL here)">

<!-- async CSS -->
<link rel="stylesheet" media="print" onload="this.onload=null;this.removeAttribute('media');" href="(font CSS URL here)">

<!-- no-JS fallback -->
<noscript>
    <link rel="stylesheet" href="(font CSS URL here)">
</noscript>

</head>

0

只需添加块标签

 https://fonts.googleapis.com/css?family=Noto+Serif&display=block

参考:控制字体


2
从您提供的链接中可以得知:"block" 会给字体设置一个短暂的块期间(在大多数情况下建议为3秒),以及一个无限的交换期间。换句话说,如果字体未加载,浏览器会首先绘制“不可见”的文本,但是一旦字体加载完成,就会立即切换字体。这意味着它将导致不可避免的 FOIT。 - Neurotransmitter

-5

好的,把这个放在body标签里而不是head标签里

   <link href="https://fonts.googleapis.com/css?family=Noto+Serif" rel="stylesheet" lazyload>

2020年更新

 <link rel="preload" as="style" href="https://yourcss.css" onload="this.rel='stylesheet'" />

62
“lazyload”属性来自W3C的一个废弃提案,仅被Internet Explorer和Edge实现了(可参考http://caniuse.com/#feat=lazyload)。我不建议在公共网站上使用它。为了在所有浏览器中异步加载Google字体,你应该使用它们的JavaScript Web Font Loader(https://github.com/typekit/webfontloader)。 - soren121
8
请查看 https://caniuse.com/#feat=lazyload 以验证 Soren 的评论,您会发现他是正确的。因此,请勿在生产环境中使用此解决方案。 - WebWorker
1
截至2020年10月,@Pavlo Razumovskyi的答案是正确的,请使用该答案,因为这也是我现在使用的。 - Paddy
我们能够在脑海中完成吗? - Reign.85

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