Skip to main content
kld.dev

This is not a Google font

January 24, 2023

I could easily reduce the size of this page by about two-thirds. How? By not using webfonts. As of writing, most of the articles on my site are less than 50KB (gzipped, and excluding a few iframes). Font files make up about 33KB of that. It’s not much, but I am trying to keep this site as tiny as possible. Webfonts are one indulgence I’m allowing, and it took some experimentation to get to this point.

System fonts

I was initially pretty happy to use a system font stack. Here is what that looks like:

body {
  font-family: system-ui, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif, 'Apple Color Emoji',
    'Segoe UI Emoji', 'Segoe UI Symbol';
}

My pages were as little as 16KB, but I really wanted my site to look polished and consistent across devices and operating systems.

Google Fonts

I considered a few different ways to use Google Fonts.

The Google Fonts API

Pulling fonts directly from Google is fast and easy. Google serves up the optimal format for your browser, as well as the subset of characters you need (i.e. Latin characters).

<link rel="preconnect" href="https://fonts.googleapis.com" />
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
<link
  href="https://fonts.googleapis.com/css2?family=Roboto:wght@400;700&display=swap"
  rel="stylesheet"
/>

The last line loads CSS onto the page, which includes a @font-face rule. That rule will contain a src that points to a font file hosted on fonts.gstatic.com. Notice the display=swap parameter in our URL. That will add font-display: swap to the rule. I will talk more about that later.

I also considered only using Google Fonts for the top-level heading. All I had to do was generate a text parameter for the Google Fonts API URL. This resulted in a very small font file that only had those exact characters.

<link rel="preconnect" href="https://fonts.googleapis.com" />
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
<link href="https://fonts.googleapis.com/css2?family=Roboto&text=Lorem+Ipsum" rel="stylesheet" />

However, that still left me wanting a webfont for the body.

Self-hosting

Who wants to feed Google more data anyway? With HTTP/2 in my favor, I might as well host the font files alongside the rest of my site’s assets. This is where the google-webfonts-helper comes in handy. It will give me the files and CSS code I need to self-host Google fonts, and it will subset the font files to only Latin characters for me.

Too cool for Google Fonts

There are hundreds of Google fonts, but in the end, I felt better purchasing a webfont from an independent foundry. I chose Strawford by atipo foundry. Their fonts are beautiful, and their licenses are reasonable. The @font-face rules in my CSS now look like this:

@font-face {
  font-family: 'Strawford';
  font-style: normal;
  font-weight: 400;
  font-display: fallback;
  src: local(''), url('/fonts/strawford-regular-webfont.woff2') format('woff2'), url('/fonts/strawford-regular-webfont.woff')
      format('woff');
}
@font-face {
  font-family: 'Strawford';
  font-style: normal;
  font-weight: 500;
  font-display: fallback;
  src: local(''), url('/fonts/strawford-medium-webfont.woff2') format('woff2'), url('/fonts/strawford-medium-webfont.woff')
      format('woff');
}

Font-display

Once I settled on a webfont that I liked, I went on my merry way. There was just one problem. My pages were loading so fast that the font files loaded after the page had already rendered. This resulted in a flash of unstyled text (FOUT) on almost every page load.

The fix for this is to change the font-display. Here are all the possible values:

  • auto: The browser does what it wants. Do not trust the browser.
  • block: The browser will render invisible text until the font loads. If your site reaaaaallly depends on that webfont, you could use this. But you probably shouldn’t.
  • swap: This is the most commonly recommended value, and it is what I started with. Text is immediately rendered using a fallback font until the webfont loads. If you are serving up a typical 2MB+ page, you should probably just use this.
  • optional: The browser renders invisible text for a very brief moment while it waits for the webfont to load. After that, it will render the fallback font, and it may decide to never even load the webfont at all.
  • fallback: Again, the browser renders invisible text for a brief moment before rendering the fallback font. However, unlike optional, the browser should be pretty lenient about waiting for that webfont to load.

As shown in my previous snippet, I went with font-display: fallback. This reduces the likelihood of FOUT, still allows for some performance gains, and is more likely to render my webfont than optional. I was afraid PageSpeed Insights would scold me for not sticking with font-display: swap, but it let me slide.

And that is how I ended up with what you see now—until I inevitably redesign everything. Again.

Other fonts

For the sake of completeness, here are the other fonts on this site currently:

  • My logo uses Marvin Visions, which is a superb variable font by Mathieu Triay. The logo is just an SVG, though. No webfont here.
  • All of the <code> elements on this page are just using the browser’s default monospace font. I think I’m okay with that. For now…