Web Fonts: From Google to Self-Hosting Like a Pro

Web DevelopmentCSSTypographyWeb Design

Web Fonts: From Google to Self-Hosting Like a Pro

If we want to use a font that doesn't come pre-installed on the user's device, we can download and use a custom font!

There are lots of ways to do it. In this lesson, we'll look at a couple of popular services that can help, and also see how to do it from scratch.

Using Google Fonts

Google Fonts is an online repository of free, open-source web fonts. They have hundreds of popular options. It also effectively works as a CDN for fonts; they serve the fonts for us, from their own servers.

Google Fonts works by providing a snippet that looks like this:

<link rel="preconnect" href="https://fonts.gstatic.com" />
<link
  href="https://fonts.googleapis.com/css2?family=Open+Sans:ital,wght@1,400;1,600&display=swap"
  rel="stylesheet"
/>

Drop this in the <head> of your HTML file.

Then use it in your CSS:

.thing {
  font-family: "Open Sans", sans-serif;
}
Quotes for font names

Web fonts should be wrapped in quotes ('Open Sans', not Open Sans). It isn't strictly required for single-word fonts, but it's good practice.

No HTML file?

If you use a framework like Next.js, you may not have a traditional index.html file.

Frameworks generate this file automatically, but they provide escape hatches. In Next.js, you can use the <Head /> component:

import Head from "next/head";

<Head>
  <link rel="preconnect" href="https://fonts.gstatic.com" />
  <link
    href="https://fonts.googleapis.com/css2?family=Open+Sans&display=swap"
    rel="stylesheet"
  />
</Head>;

The Benefits and Downsides of Google Fonts

Easy setup, but not perfect

Google Fonts is convenient, but not always the best for performance or variety.

  • Lots of amazing fonts aren't on Google Fonts
  • Self-hosted web fonts can perform better

Gatsby creator Kyle Matthews discovered that self-hosting fonts can save 300ms on desktop and 1s+ on mobile 3G.

Performance Trade-Offs

The issue isn't Google's server speed — it's about the loading process:

  1. Browser fetches and parses index.html
  2. It sees the <link> to Google Fonts CSS, fetches it
  3. Parses that CSS, sees font reference to fonts.gstatic.com, fetches it too

Because fonts.googleapis.com and fonts.gstatic.com are external domains, additional handshakes (like HTTPS) introduce overhead.

Blocking requests hurt performance

The font CSS request is blocking — the browser waits before rendering the page.

Self-hosting lets you skip Step 2 and 3 entirely, resulting in better performance.

In the past, fonts from Google Fonts might've been cached due to global CDN sharing. However, modern browsers now use partitioned caches, so every site must re-download fonts.

Using Modern Tooling: Fontsource

Fontsource by Vercel makes it easy to self-host fonts. You can install fonts using npm:

npm install @fontsource/open-sans

Then import it directly:

import "@fontsource/open-sans";
Fontsource FTW

Fontsource supports all Google Fonts and other open-source fonts, ideal for modern JS frameworks.

Angular 11+ also supports Google Fonts with built-in configuration to inline fonts directly.

The Manual Way

If the font isn't on Google Fonts or Fontsource, self-host manually.

Converting formats

Most system fonts are .otf or .ttf — large and not optimized for web. Convert them to .woff2 using Font Squirrel's Webfont Generator.

Using @font-face

@font-face {
  font-family: "Wotfard";
  src: url("/fonts/wotfard-regular.woff2") format("woff2");
  font-weight: 400;
  font-style: normal;
}

Repeat for each weight and style:

@font-face {
  font-family: "Wotfard";
  src: url("/fonts/wotfard-medium.woff2") format("woff2");
  font-weight: 500;
  font-style: normal;
}

@font-face {
  font-family: "Wotfard";
  src: url("/fonts/wotfard-bold.woff2") format("woff2");
  font-weight: 700;
  font-style: normal;
}

@font-face {
  font-family: "Wotfard";
  src: url("/fonts/wotfard-regular-italic.woff2") format("woff2");
  font-weight: 400;
  font-style: italic;
}

Each variation (italic, weight) requires its own declaration.

IE Support

Modern browsers all support .woff2. IE doesn't.

@font-face {
  font-family: "Wotfard";
  src: url("/fonts/wotfard-regular-italic.woff2") format("woff2"), url("/fonts/wotfard-regular-italic.woff")
      format("woff");
  font-weight: 400;
  font-style: normal;
}

Put .woff2 first so modern browsers use the smaller file.

Where to Place the Fonts

Add @font-face declarations inside <style> in your index.html or in your main CSS file.

<style>
  @font-face {
    font-family: "Wotfard";
    src: url("/fonts/wotfard-regular.woff2") format("woff2");
    font-weight: 400;
    font-style: normal;
  }
</style>

Use like this:

.something {
  font-family: "Wotfard";
  font-weight: 400;
}

Static Files in React

React requires assets like fonts/images to go in the public/ folder (CRA) or static handling paths for frameworks like Next.js and Gatsby.

Faux Bolds and Italics

Without the real bold or italic font, browsers will simulate styles. These look worse than true variants.

True Bold – Clean and designed by the font creator.

Faux Bold – Lines artificially thickened by the browser.

Same goes for italic: browsers slant the font instead of using alternate characters.

Use real styles

Always provide actual bold/italic font files. Faux styles reduce visual quality.

Number Rounding

Suppose you load 400 and 900 weights. What happens when you write:

.thing {
  font-weight: bold;
}

.thing {
  font-weight: 700;
}

In the past, this would result in faux-bold. But modern browsers round to the closest available weight.

Demo Outcome

The font will round to 900, showing heavy text for both weights.

Using font-weight: bold

Using font-weight: 700

This text is bold.This text is bold.
Use numeric weights for clarity

Use font-weight: 700 instead of bold for better control and precision.

Final Thoughts

  • Google Fonts is simple, but may be slower
  • Self-hosted fonts are faster and more customizable
  • Fontsource makes self-hosting even easier
  • Always use proper formats (.woff2, .woff)
  • Avoid faux styles — real bold/italic files make a difference