Skip to content

Font Optimization

Fonts loaded from external CDNs (like Google Fonts' default embed snippet) add extra network requests and can cause layout shift as text re-renders once the font loads. next/font solves both problems automatically.

Self-Hosting Fonts Automatically

next/font downloads your chosen font files at build time and serves them from your own domain instead of an external CDN, removing an extra DNS lookup and network round-trip that the traditional Google Fonts <link> tag requires. It also automatically applies font-display: optional (or a similar strategy) and calculates fallback font metrics to minimize layout shift while the font loads.

This works for both Google Fonts (via next/font/google) and self-hosted custom font files (via next/font/local), with the same API for both.

// app/layout.tsx
import { Inter } from "next/font/google";

const inter = Inter({ subsets: ["latin"] });

export default function RootLayout({ children }: { children: React.ReactNode }) {
  return (
    <html lang="en" className={inter.className}>
      <body>{children}</body>
    </html>
  );
}

This one import self-hosts Inter automatically, with no manual font file downloading or <link> tags required.

next/font Usage Shape

import { FontName } from "next/font/google";

const fontName = FontName({
  subsets: ["latin"],
  weight: ["400", "700"],
  display: "swap",
});

// apply via className or variable
<div className={fontName.className}>...</div>
  • subsets limits which character sets are downloaded, keeping the font file smaller.
  • weight specifies which font weights to include; omit for variable fonts that support all weights.
  • className applies the font directly; variable exposes it as a CSS custom property for more flexible use.
  • next/font/local uses the same API for self-hosted font files you provide yourself.

Font Optimization Cheat Sheet

Key facts about next/font.

Feature Benefit
Self-hosting No external font CDN request
Automatic fallback metrics Reduces layout shift while the font loads
next/font/google Google Fonts, downloaded and self-hosted at build time
next/font/local Custom, self-hosted font files
variable option Exposes the font as a CSS custom property

Using Multiple Fonts with CSS Variables

For designs using more than one font family (e.g. a heading font and a body font), the variable option exposes each font as a CSS custom property, letting you apply them selectively via your stylesheet rather than only through a single root className.

import { Inter, Playfair_Display } from "next/font/google";

const inter = Inter({ subsets: ["latin"], variable: "--font-body" });
const playfair = Playfair_Display({ subsets: ["latin"], variable: "--font-heading" });

// app/layout.tsx
<html className={`${inter.variable} ${playfair.variable}`}>

/* globals.css */
h1, h2, h3 { font-family: var(--font-heading); }
body { font-family: var(--font-body); }

Self-Hosting Custom Font Files

For custom, non-Google fonts (like a brand's licensed typeface), next/font/local applies the exact same optimization benefits to font files you already have.

import localFont from "next/font/local";

const brandFont = localFont({
  src: "./fonts/BrandFont.woff2",
});

Common Mistakes

  • Continuing to use the traditional Google Fonts <link> tag instead of next/font/google.
  • Loading every font weight/style available instead of only the ones actually used, bloating file size.
  • Applying a font's className too narrowly, causing inconsistent typography across the page.
  • Not using variable when multiple fonts need to coexist in the same stylesheet.

Key Takeaways

  • next/font self-hosts fonts automatically, removing external CDN requests entirely.
  • It calculates fallback font metrics to minimize layout shift while fonts load.
  • next/font/google and next/font/local share the same API for Google and custom fonts.
  • The variable option supports using multiple fonts via CSS custom properties.
  • Loading only the subsets/weights you actually use keeps font payload size minimal.

Pro Tip

Apply your font's className on the <html> element in the root layout rather than scattering it across individual components — this guarantees consistent typography everywhere and lets you use CSS variables selectively for any secondary fonts.