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
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.
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.