49

I want to use the Google Font "Noto Serif" for my website. My problem is that when I am testing it with Google PageSpeed Insights, it says everything is perfect except for one thing:

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

Your page has 1 blocking CSS resources. This causes a delay in rendering your page. None of the above-the-fold content on your page could be rendered without waiting for the following resources to load. Try to defer or asynchronously load blocking resources, or inline the critical portions of those resources directly in the HTML.

I am aware of a bad solution for this. It's to link the font using <script> at the bottom of the HTML file. The problem with that solution is it causes a Flash of Unstyled Text every time you click on something in my website.

I am using jekyll hosted with GitHub Pages, so I don't think I can install Font Face Observer :(

Piyush Pranjal
  • 414
  • 4
  • 11
oatmealNUGGY
  • 775
  • 1
  • 6
  • 22

7 Answers7

23

You can load the web fonts asynchronously with this script:

<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>

You'll need this library, it's pretty easy to implement. I've learn this from a course I took recently, Responsive Web Design Fundamentals, if you're interested you can check it out here.

szymond
  • 1,311
  • 2
  • 19
  • 41
Mirza Sisic
  • 2,401
  • 4
  • 24
  • 38
  • 6
    The library (webfontloader) seems to be [no longer maintained](https://github.com/typekit/webfontloader/issues/411). Also some peeople have [issues with it working in IE and edge](https://github.com/typekit/webfontloader/issues/388). I have doubts about using it. – szymond May 16 '19 at 15:21
  • Thanks for the heads up and the edit, I've haven't used it in about a year. – Mirza Sisic May 31 '19 at 20:17
  • 3
    Keep in mind, that this will prevent font loading when JavaScript is disabled. – Neurotransmitter Jan 10 '20 at 12:06
  • 1
    @Neurotransmitter Agree. Better to put a `noscript` tag with the original `link` tag inside. That would make the font load like normal when JS is disabled. – Jongwoo Lee Sep 28 '21 at 12:49
19

Based on this strategy to preload stylesheets:

<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;
}
  • Do you think it's affect the swap display type that google fonts API give?. Google Fonts give this URL for Roboto font `https://fonts.googleapis.com/css2?family=Roboto:wght@400&display=swap` – Lucas Vazquez Apr 16 '20 at 02:12
  • 1
    @pavlo keep in mind that this is not yet fully supported and the styles won't load everywhere: https://caniuse.com/#search=preload – retrovertigo Jun 01 '20 at 01:39
  • 1
    Check out https://walterebert.com/playground/css/async/ – Raffi Jul 26 '21 at 22:28
5

Add two attributes to your code. One is rel="preload" and the other is as="style". The final code would look like the below:

<link href="https://fonts.googleapis.com/css?family=Noto+Serif" rel="stylesheet" rel="preload" as="style">
Usman Ahmed
  • 2,392
  • 1
  • 20
  • 17
  • As far as I can tell, this doesn't work. If you have duplicate `rel` attributes, then the last one "overrides" the preceding ones, so `rel="preload"` is ignored. You need to only have the `rel="preload"` and then switch it to `rel="stylesheet"` after it's loaded, like [this answer](https://stackoverflow.com/a/72422314/11950764) that I just added. – joe May 29 '22 at 09:10
2

Very simple approach:

<link rel="preload" href="styles.css" as="style" onload="this.onload=null;this.rel='stylesheet'">

Just replace styles.css with your font URL. It loads the font, and then once it finishes (onload) it "enables" it by switching the rel property to stylesheet.

More details here.

joe
  • 3,752
  • 1
  • 32
  • 41
0

Only add block tag

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

Ref : Controlling Font

Cristian Q
  • 617
  • 5
  • 9
  • 2
    From the link you provided: "block gives the font face a short block period (3s is recommended in most cases) and an infinite swap period. In other words, the browser draws "invisible" text at first if the font is not loaded, but swaps the font face in as soon as it loads". Which means it will lead to an inevitable FOIT. – Neurotransmitter Jan 10 '20 at 12:09
0

Has any one tried this solution?

<!-- 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>
Primoz Rome
  • 10,379
  • 17
  • 76
  • 108
-5

Here ya go, include this in the body tag and not the head tag

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

Updated 2020

 <link rel="preload" as="style" href="https://yourcss.css" onload="this.rel='stylesheet'" />
Paddy
  • 772
  • 2
  • 11
  • 28
  • 62
    @StuffedMarshmallow The "lazyload" attribute comes from an abandoned W3C proposal, and [it was only implemented by Internet Explorer and Edge](http://caniuse.com/#feat=lazyload). I would not recommend using it on a public website. To asynchronously load Google Fonts in _all_ browsers, you should use [their JavaScript Web Font Loader](https://github.com/typekit/webfontloader). – soren121 Jan 19 '17 at 23:56
  • 8
    To proof the comment of soren please check https://caniuse.com/#feat=lazyload and you'll see he ist right. So do not use this solution in your production environment. – WebWorker Feb 01 '18 at 07:40
  • 1
    as of October 2020 @Pavlo Razumovskyi has the correct answer, please use that, as this is what I now use as well. – Paddy Oct 22 '20 at 01:40
  • we can do it on head ? – Reign.85 Aug 26 '22 at 08:56