Next.js Font Optimization

Load web fonts in Next.js with next/font for fast pages and no layout shift.

TL;DR

  1. Import a font from next/font/google and call it once.
  2. Apply the font with its className on the html tag.
  3. Load your own files with localFont from next/font/local.

Google Fonts

    next/font/google

    Import a font by name and call it once at the top of a module.

    import { Inter } from 'next/font/google';
    
    const inter = Inter({ subsets: ['latin'] });
    className

    Apply the font to the whole app by adding its class to the html tag.

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

    List the weights you need for fonts that are not variable fonts.

    import { Roboto } from 'next/font/google';
    
    const roboto = Roboto({
      weight: ['400', '700'],
      subsets: ['latin'],
    });

Local Fonts

    next/font/local

    Load a font file from your project with the localFont function.

    import localFont from 'next/font/local';
    
    const brand = localFont({
      src: './fonts/Brand.woff2',
    });
    Multiple Files

    Pass an array when each weight or style lives in its own file.

    const brand = localFont({
      src: [
        { path: './Brand-Regular.woff2', weight: '400' },
        { path: './Brand-Bold.woff2', weight: '700' },
      ],
    });
    display

    Control how text shows while the font file is still loading.

    const brand = localFont({
      src: './fonts/Brand.woff2',
      display: 'swap',
    });

CSS Variables and Tailwind

    variable

    Expose the font as a CSS variable instead of applying it directly.

    const inter = Inter({
      subsets: ['latin'],
      variable: '--font-inter',
    });
    
    <html className={inter.variable}>
    var()

    Use the variable anywhere in your stylesheet with the var function.

    body {
      font-family: var(--font-inter), sans-serif;
    }
    @theme

    Map the variable to a Tailwind font utility in Tailwind CSS version 4.

    /* app/globals.css */
    @import 'tailwindcss';
    
    @theme inline {
      --font-sans: var(--font-inter);
    }

Multiple Fonts

    app/fonts.ts

    Define every font in one file so the whole app shares the same instances.

    // app/fonts.ts
    import { Inter, Lora } from 'next/font/google';
    
    export const inter = Inter({
      subsets: ['latin'],
      variable: '--font-inter',
    });
    export const lora = Lora({
      subsets: ['latin'],
      variable: '--font-lora',
    });
    Combine Variables

    Add several font variables to the html tag in one class string.

    const fonts = `${inter.variable} ${lora.variable}`;
    
    <html lang="en" className={fonts}>
    One Element

    Apply a second font to a single element with its own class name.

    import { lora } from '@/app/fonts';
    
    <h1 className={lora.className}>Welcome</h1>

Tips

  1. Choose a variable font when one exists, so a single file covers every weight without listing them in weight.
  2. Define each font once in a shared file such as app/fonts.ts, so every import reuses the same instance.

Warnings

  1. A non-variable Google font needs an explicit weight option, or the build fails with a missing weight error.
  2. Calling a next/font loader inside a component is not allowed, so call it at the top level of a module.

In Practice

FAQ