Load web fonts efficiently with next/font for performance and UX.
import { Inter } from "next/font/google";
const inter = Inter({ subsets: ["latin"] });
export default function RootLayout({ children }) {
return (
<html className={inter.className}>
<body>{children}</body>
</html>
);
}import { Inter, Playfair_Display } from "next/font/google";
const inter = Inter({ subsets: ["latin"] });
const playfair = Playfair_Display({
weight: ["400", "700"],
subsets: ["latin"]
});
export default function Page() {
return (
<div>
<h1 className={playfair.className}>Title</h1>
<p className={inter.className}>Body text</p>
</div>
);
}const inter = Inter({ subsets: ["latin"], variable: "--font-inter" });
export default function RootLayout({ children }) {
return <html className={inter.variable}>{children}</html>;
}
// In CSS: font-family: var(--font-inter);// lib/fonts.ts
import { Inter, Roboto_Mono } from "next/font/google";
export const inter = Inter({ subsets: ["latin"] });
export const mono = Roboto_Mono({ subsets: ["latin"] });const inter = Inter({
weight: ["400", "500", "700"],
subsets: ["latin"]
});const playfair = Playfair_Display({
subsets: ["latin"], // Only Latin characters
display: "swap" // Show fallback while loading
});const font = Inter({
display: "swap", // Show fallback immediately
// "auto" (default), "block", "fallback", "optional"
});const inter = Inter({
subsets: ["latin"],
adjustFontFallback: true // adjusts metrics of fallback font
});const inter = Inter({
subsets: ["latin"]
// Inter is a variable font — no weight array needed
});import localFont from "next/font/local";
const customFont = localFont({
src: [
{
path: "../fonts/custom.woff2",
weight: "400",
style: "normal"
},
{
path: "../fonts/custom-bold.woff2",
weight: "700",
style: "normal"
}
]
});public/
fonts/
custom.woff2
custom-bold.woff2export default function RootLayout({ children }) {
return (
<html className={customFont.className}>
<body>{children}</body>
</html>
);
}const customFont = localFont({
src: "../fonts/custom.woff2",
variable: "--font-custom"
});
// tailwind.config: fontFamily: { brand: ["var(--font-custom)"] }const inter = Inter({
display: "swap", // Shows fallback font immediately
subsets: ["latin"]
});// app/layout.tsx (root layout)
import { Inter } from "next/font/google";
const inter = Inter();
export default function RootLayout({ children }) {
return <html className={inter.className}>{children}</html>;
}const inter = Inter({
subsets: ["latin", "latin-ext"] // Add extended Latin
});import { getCLS } from "web-vitals";
getCLS(console.log); // CLS score should be near 0 with font optimizationconst mono = Roboto_Mono({
subsets: ["latin"],
preload: false // Only loaded when used, not preloaded
});Import the font from next/font/google and call it as a function with your desired options — Next.js automatically downloads the font files at build time and serves them from your own domain, eliminating third-party requests.
Yes, import and instantiate each font separately from next/font/google, then apply their .className or CSS variable to the relevant elements. Keep the total count to 2–3 families to avoid unnecessary payload growth.
A standard @import fetches fonts from Google's CDN at runtime, which adds a render-blocking network request and can hurt Core Web Vitals. next/font self-hosts the files and injects optimized <link> tags with zero layout shift.
Pass weight and subsets arrays when instantiating the font, e.g. weight: ['400', '700'] and subsets: ['latin'] — only those variants are bundled, keeping the font payload as small as possible.
Import localFont from next/font/local and point src at your font file (or an array of files for multiple weights/styles) inside the public or app directory — you get the same automatic optimization as with Google Fonts.