Adding Google Fonts to Your Next.js App

Johnny AM

Overview

Typography can make your application come to life. Adding Google fonts (or custom fonts) to your Next.js project takes a few simple steps.

I wrote a short explanation of Web Fonts here that provides additional helpful details.

The information here will allow you to use Google Fonts in the way that makes the most sense for your project.

The Options

I'll cover 3 ways to include Google Fonts to a Next.js project. Feel free to pick the approach that makes sense for you.

Option 1: Reference Google fonts from CDN

This is usually my preferred method because it's quick to get going and avoids using another external package for something relatively simple.

Option 2: Utilize an NPM Package

This is a good option if you don't mind adding an npm package to take care of this for you. The NPM package I'll cover also does some optimizations that will help with your lighthouse score.

Option 3: Download and reference fonts locally

This is a good option if you prefer not to depend on Google.com (user privacy). This might also make sense if you pair your Google font with a custom font from a different 3rd party provider (consistency).

Option 1: Reference Google Fonts from CDN

This is frequently my initial approach to adding Google Fonts (though I may change later as the project matures).

I like this approach because it's fairly easy to setup and doesn't require depending on another NPM package. Version upgrades happen often (especially in Next.js), and keeping your project references updated (and testing after each upgrade) can become a burden.

Step 1: Create Emtpy Project


> yarn create next-app
  

Step 2: Add a Custom Document File

Next.js has two special documents/component types that we'll use to add Google Fonts. They are _document.js and _app.js. I include these two files in all my projects for other purposes, so this is natural step.

First let's create the pages/_document file with the code


import Document, { Html, Head, Main, NextScript } from 'next/document'

class MyDocument extends Document {
  static async getInitialProps(ctx) {
    const initialProps = await Document.getInitialProps(ctx)
    return { ...initialProps }
  }

  render() {
    return (
      <Html>
        <Head>
          <link href="https://fonts.googleapis.com/css2?family=Lobster&display=swap" rel="stylesheet" />
        </Head>
        <body>
          <Main />
          <NextScript />
        </body>
      </Html>
    )
  }
}

export default MyDocument
  

This is boilerplate code pulled from the custom document documentation page. We added the link tag that references a Google font (Lobster in this case).

Here we'll use the Google Hosted with Link tag method.

Next.js has an advanced feature called a Custom Document that allows you to augment your overall HTML document. In this case, we are looking to add a link tag to download the hosted google font in the document head.

Create a new file at pages/_document.js and add the contents

Create an empty Next.js project

Let's create a standard Next.js project and accept the default starter app.


> yarn create next-app
  

Use a Link Tag (Option 1 - my current preference)

Here we'll use the Google Hosted with Link tag method.

Next.js has an advanced feature called a Custom Document that allows you to augment your overall HTML document. In this case, we are looking to add a link tag to download the hosted google font in the document head.

Create a new file at pages/_document.js and add the contents


import Document, { Html, Head, Main, NextScript } from 'next/document'

class MyDocument extends Document {
  static async getInitialProps(ctx) {
    const initialProps = await Document.getInitialProps(ctx)
    return { ...initialProps }
  }

  render() {
    return (
      <Html>
        <Head>
          <link href="https://fonts.googleapis.com/css2?family=Lobster&display=swap" rel="stylesheet" />
        </Head>
        <body>
          <Main />
          <NextScript />
        </body>
      </Html>
    )
  }
}

export default MyDocument
  

You'll notice the Lobster font type referenced in the Link tag. I used Lobster because it's different from the default Next.js font and fallbacks: -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Oxygen, Ubuntu, Cantarell, Fira Sans, Droid Sans, Helvetica Neue, sans-serif;

Use the font you prefer by visiting Google Fonts and grabbing the corresponding <link> tag.

Now, update the default css font-family rule in pages/index.js. You'll find this at the bottom of the index page. Replace the <style jsx global> tag with:


<style jsx global>{`
  html,
  body {
    padding: 0;
    margin: 0;
    font-family: Lobster;
  }

  * {
    box-sizing: border-box;
  }
`}</style>
  

Run your project with yarn dev. You should see the before and after screenshot of the font change. You'll notice the font on the right is now Lobster.


If you're on a Windows PC or Android, you may see a different default font (left side) here (I'm on macOS)

Use an @import CSS Rule (Option 2)

Your second option is to use a CSS @import rule to reference the Gooogle hosted font. You'll want to do this before any of your CSS classes reference the font. You can add this to the <style jsx global> tag that comes with the default Next.js project, but I prefer the flexibility of adding my own CSS class.

To add a CSS class, you need to add a custom _app component (learn more about custom apps). Add a new page called _app.js in the root of your project (pages/_app.js) with the content


import '../css/main.css'

function MyApp({ Component, pageProps }) {
  return <Component {...pageProps} />
}

export default MyApp
  

Next, you'll create a new directory called css in the root of your project, and a file named main.css in that directory (css/main.css)


@import url('https://fonts.googleapis.com/css2?family=Lobster&display=swap');

/* can now reference my font */
body {
  font-family: Lobster;
}

/* my custom css */
  

Host your fonts locally

You'll need to define your own @font-face CSS rule if you purchased fonts or prefer to host them locally. The @font-face CSS rule contains the attributes that define your font.

You can read more about Web Fonts or the @font-face CSS rule.

In Next.js, you can add your fonts to the public directory. I recommend creating a public/fonts. You would then reference your fonts location in your @font-face like this.

In Next.js, you can add your fonts to the public directory. I recommend creating a public/fonts directory to store them. The @font-face CSS rule can then reference your font location like this.


/* this is an abbreviated version of @font-face, meant to show how to reference the font in the relative url attribute.
/* assuming the fonts were stored in public/fonts */

@font-face {
  font-family: 'Roboto';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: local('Roboto'), url(/fonts/roboto.woff2) format('woff2');
}
  

Common Questions / Answers

Why not use the next-google-fonts package to add fonts?

The next-google-fonts NPM package is great solution. My goal was to unpack how Google fonts and Next.js work together in case you prefer not to use an NPM package. Furthermore, if you have a custom font or prefer to host the Google font locally, the NPM package won't work in that scenario.

An advantage of using the NPM package is the optimization techniques included for faster loading and better lighthouse scores.

How performant is this approach? How do I increase my lighthouse score?

I have not shown many of the optiimization techniques to help with faster font loading. I can evolve this article if the demand is there. Ultimately YMMV with each approach. There are lots of conflicting reports and tests on which techniques are best practices and have the most positive impact.

I would encourage you to test with your specific site/app and use the dev tools combined with "disable cache" and the built-in ability to change connection speeds.

Terms of Service  |  Privacy Policy

© 2020 johnny.am. All rights reserved.