How to load (and preload) fonts

In the first version of our framework custom fonts weren’t supported but now we need to recommend the best way to do it, so we need to investigate this a bit :slight_smile:

This is an interesting article about when should fonts be loaded and how to use link preload to optimize the whole process:
https://andydavies.me/blog/2019/02/12/preloading-fonts-and-the-puzzle-of-priorities/

Feel free to comment or include more interesting articles or insights!

Any idea on what’s the best way to import local fonts?

I noticed that if I import the fonts and define the @font-faces inside <Global /> the fonts are requested twice: once on the initial load, and once on the hydration. And after that, every time <Global /> is rendered the fonts are requested again. It would be good to have a recommended way to do this.

I was thinking on moving the @font-face definitions outside of React, but I’m not sure what’s the right way to do that.

We aren’t doing anything different than what is done by Emotion, so I guess the best way to deal with fonts in Emotion will be the best way to deal with fonts in Frontity.

@orballo have you taken a look at how is this usually solved by people using Emotion (or even styled-components)?

I tried to load fonts but I can’t find a example to work with Frontity. Even If I try to load the font file located on assets/fonts/font.xxx it returns 404.

Can you write a code example?

I haven’t explored this further yet. The temporary solution I have is to render a <Global /> component with the @font-face definitions, but the problem here is that the fonts will be required twice on load, because of the hydration of React, causing some flickering.

Imports:

import { css, Global } from "frontity";
import LibreBaskerville from "../../fonts/LibreBaskerville-Regular.ttf";

Font face definition:

<Global
      styles={css` 
        @font-face {
          font-family: "Libre Baskerville";
          font-style: normal;
          font-weight: normal;
          font-display: fallback;
          src: url("${LibreBaskerville}") format("truetype");
        }
    `}
/>

The ideal solution I think is to load the fonts outside of the React cycle somehow. Not sure how to do this and I couldn’t find a quick solution around, need to explore it more.

It is important that you define the @font-face in a separeted <Global /> element because if you do this in an existing <Global /> element that might be using a state variable and is subject to rerender, the @font-face definition would be rerendered as well, asking again for the fonts and causing the flickering.

I tried this but I get the following error:

ERROR in ./packages/competicion-theme/src/assets/fonts/Metropolis-Bold.ttf 1:0
    Module parse failed: Unexpected character '' (1:0)
    You may need an appropriate loader to handle this file type, currently no loaders are configured to process this file. See https://webpack.js.org/concepts#loaders
    (Source code omitted for this binary file)

Are you running the last version of frontity? The webpack's font loaders were added after the 1.0 so maybe you are missing that update? I didn’t run into that problem.