Next.js Font Optimization
Load web fonts in Next.js with next/font for fast pages and no layout shift.
TL;DR
- Import a font from
next/font/googleand call it once. - Apply the font with its
classNameon thehtmltag. - Load your own files with
localFontfromnext/font/local.
Google Fonts
next/font/googleImport 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'] });classNameApply 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>
);
}weightList 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/localLoad a font file from your project with the localFont function.
import localFont from 'next/font/local';
const brand = localFont({
src: './fonts/Brand.woff2',
});Multiple FilesPass 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' },
],
});displayControl how text shows while the font file is still loading.
const brand = localFont({
src: './fonts/Brand.woff2',
display: 'swap',
});CSS Variables and Tailwind
variableExpose 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;
}@themeMap 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.tsDefine 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 VariablesAdd several font variables to the html tag in one class string.
const fonts = `${inter.variable} ${lora.variable}`;
<html lang="en" className={fonts}>One ElementApply a second font to a single element with its own class name.
import { lora } from '@/app/fonts';
<h1 className={lora.className}>Welcome</h1>Tips
- Choose a variable font when one exists, so a single file covers every weight without listing them in
weight. - Define each font once in a shared file such as
app/fonts.ts, so every import reuses the same instance.
Warnings
- A non-variable Google font needs an explicit
weightoption, or the build fails with a missing weight error. - Calling a
next/fontloader inside a component is not allowed, so call it at the top level of a module.
In Practice
Load a body font and a heading font, then use both through Tailwind utility classes.
- Each font gets a CSS variable, so styles can refer to it by name.
- Both variables go on the html tag, which makes them available everywhere.
- The theme block in globals.css maps them to font-sans and font-serif.
- Headings then only need the font-serif class to switch fonts.
// app/layout.tsx
import { Inter, Lora } from 'next/font/google';
import './globals.css';
const inter = Inter({
subsets: ['latin'],
variable: '--font-inter',
});
const lora = Lora({
subsets: ['latin'],
variable: '--font-lora',
});
const fonts = `${inter.variable} ${lora.variable}`;
type Props = { children: React.ReactNode };
export default function RootLayout({ children }: Props) {
return (
<html lang="en" className={fonts}>
<body className="font-sans">{children}</body>
</html>
);
}FAQ
Import the font from next/font/google, call it with subsets: ['latin'], and put the returned className on your tag in app/layout.tsx.
No. Next.js downloads the font files at build time and serves them from your own domain. The browser never contacts Google.
Give the font a variable name such as --font-inter and add that class to . Then map it in your CSS with @theme inline { --font-sans: var(--font-inter); }.
Import localFont from next/font/local and pass the path to your .woff2 file in src. Use the returned className like any other font.