How to only PRELOAD a font if it doesn't exist localy?

Viewed 245

On my website, I want to strive for reducing the page size as much as possible. As such, on Apple devices - I want to display my site using the native San Francisco font. On all other devices, I want to display (the extremely similar) Roboto font.

What's great about Roboto is that it's locally installed with Android ... and as such, I don't want to install the font if it already exist.

What I want to do is, is what's describen in the pseudo code below

if ("San Francisco" or "Roboto" not installed locally) {
// download Robot (and preload it for super fast performance)
<link rel="preload" as="font" href="/assets/fonts/roboto.woff2" type="font/woff2" crossorigin/>
}

I totally realize in my CSS, it already has the ability to fallback to another font like so

body { font:normal 1em -apple-system,"Roboto",sans-serif;}

The problem with the CSS code above, it slow and doesn't preload.

Now yes, I guess I could just PRELOAD the Roboto font for ALL page views, but that's seems completely wasteful.

Thoughts on how I can do this?

1 Answers

One way to do this is through JS and the CSS Font Loading API.

You can start by trying to load the local "San Francisco" font from a FontFace instance, if it fails, load the Roboto fallbacks.
But doing so, we loose some of the advantages of link preload and we may face a Flash Of Unstyled Content.

(async () => {
  const sanfrancisco = new FontFace( "San Francisco", "local('San Francisco')" );
  try {
    await sanfrancisco.load();
    console.log( "'San Francisco' font is available on this system" );    
    document.fonts.add( sanfrancisco );
  }
  catch( err ) {
    console.log( "'San Francisco' font is not available on this system" );
    // use the local version
    // or fallback to the online one if not available
    const roboto = new FontFace( "Roboto", `local(Roboto),
      url(https://fonts.gstatic.com/s/roboto/v20/KFOmCnqEu92Fr1Mu4mxKKTU1Kg.woff2)
    ` );
    await roboto.load();
    console.log( "Roboto font loaded" );
    document.fonts.add( roboto );
  }
  document.body.classList.add( "font-loaded" ); // avoid FOUC
})();
body:not(.font-loaded) {
  opacity: 0;
}
.my-font {
  font-family: 'San Francisco','Roboto';
}
The following paragraph
<p class="my-font">uses either San Francisco or Roboto.</p>

Related