DEV Community

loading...
Ficus

Delay font loading using Javascript

Matt Levy
・2 min read

Achieving 100% across the board in Lighthouse can be tricky to do.

alt text

One of the assets of any web application is fonts. Loading fonts can have an impact on page load times and directly affects Lighthouse scores.

Fonts are often placed in the page <head> using a <link> tag.

<link href="https://fonts.googleapis.com/css2?family=Roboto&display=swap" rel="stylesheet"> 
Enter fullscreen mode Exit fullscreen mode

Whilst this is the recommended way to load fonts, style sheets loaded in the <head> block rendering and impact page load times.

A simple solution

Whilst Javascript shouldn't be used in place of HTML or CSS, it does offer the ability to create a simple solution that doesn't impact load times and takes one step closer to the 100% Lighthouse score.

The following snippet delays the loading of fonts until the page has loaded. This means that fonts are not available whilst the page is being rendered, they are rendered after page load.

['https://fonts.googleapis.com/css2?family=Roboto&display=swap'].forEach(function (f) {
  const gf = document.createElement('link')
  gf.rel = 'stylesheet'
  gf.href = f
  gf.type = 'text/css'
  const gd = document.getElementsByTagName('link')[0]
  gd.parentNode.insertBefore(gf, gd)
})
Enter fullscreen mode Exit fullscreen mode

This snippet of Javascript relies on an existing <link> tag to exist in the <head> so it can attach the font stylesheet. If you are using Google fonts or other CDN, it is recommended to use a rel="preconnect" link tag to tell the browser to establish an early connection with that origin.

<link rel="preconnect" href="https://fonts.gstatic.com">
Enter fullscreen mode Exit fullscreen mode

How to use

Copy the following Javascript into a file named fonts.mjs and include URLs to the style sheets you want to load:

['https://fonts.googleapis.com/css2?family=Roboto&display=swap'].forEach(function (f) {
  const gf = document.createElement('link')
  gf.rel = 'stylesheet'
  gf.href = f
  gf.type = 'text/css'
  const gd = document.getElementsByTagName('link')[0]
  gd.parentNode.insertBefore(gf, gd)
})
Enter fullscreen mode Exit fullscreen mode

Add a <script> tag to your HTML page pointing to the Javascript file:

<script type="module" src="/path/to/fonts.mjs"></script>
Enter fullscreen mode Exit fullscreen mode

Discussion (2)

Collapse
idarek profile image
Dariusz Więckiewicz • Edited

How about CLS? I can bet that once site is loaded it's shifting a lot and that's not user friendly really.

Collapse
ducksoupdev profile image
Matt Levy Author

Yes agreed, it can be an issue with certain fonts so definitely something to bear in mind. I have been working with sans-serif fonts where the layout shift is minimal and performance is more important on first load.