~2 min read • Updated Dec 13, 2025
Why Use next/font?
| Old Problem | next/font Solution |
|---|---|
| Google request | Downloaded at build time |
| Layout Shift | CLS = 0 |
| Privacy leak | No trackers |
| Slow loading | Local fonts |
1. Google Fonts — As Easy as Breathing
import { Inter, Roboto_Mono } from 'next/font/google'
const inter = Inter({
subsets: ['latin'],
display: 'swap',
variable: '--font-inter',
})
const roboto_mono = Roboto_Mono({
subsets: ['latin'],
weight: '400',
variable: '--font-mono',
})In layout:
<html className={`${inter.variable} ${roboto_mono.variable}`}>2. Local Fonts — Your Custom Love
import localFont from 'next/font/local'
const vazir = localFont({
src: './fonts/Vazir.woff2',
variable: '--font-vazir',
display: 'swap',
})For multiple weights:
src: [
{ path: './Vazir-Thin.woff2', weight: '100' },
{ path: './Vazir-Regular.woff2', weight: '400' },
{ path: './Vazir-Bold.woff2', weight: '700' },
]3. Tailwind CSS + next/font = True Love
// layout.tsx
<html className={`${inter.variable} ${roboto.variable} antialiased`}>
// tailwind.config.ts
fontFamily: {
sans: ['var(--font-inter)'],
mono: ['var(--font-mono)'],
}In JSX:
<p className="font-sans">Regular text</p>
<code className="font-mono">Code</code>4. Font Definitions File — Clean & Organized
// styles/fonts.ts
export const inter = Inter({ subsets: ['latin'], variable: '--font-inter' })
export const vazir = localFont({ src: './Vazir.woff2', variable: '--font-vazir' })// app/page.tsx
import { inter, vazir } from '@/styles/fonts'
<h1 className={vazir.className}>Hello World</h1>
<p className={inter.className}>Welcome</p>5. How to Apply Fonts
- className:
<p className={inter.className}> - style:
<p style={inter.style}> - CSS Variable:
font-family: var(--font-inter)
6. Preloading — Only What’s Needed
| Where | What Gets Preloaded |
|---|---|
| app/layout.tsx | All pages |
| app/dashboard/layout.tsx | Only dashboard |
| app/page.tsx | Only home |
7. Best Practices
- ✅ Use
variablefor Tailwind - ✅ Define
subsetsto reduce size - ✅ Use
display: 'swap'to avoid CLS - ✅ Define fonts in
fonts.tsfor clarity - ✅ Use variable fonts when possible
8. Real-World Example: E-Commerce Site
// styles/fonts.ts
export const inter = Inter({ subsets: ['latin'], variable: '--font-inter' })
export const playfair = Playfair_Display({ weight: '700', variable: '--font-title' })// layout.tsx
<html className={`${inter.variable} ${playfair.variable}`}>
<body className={inter.className}>{children}</body>
</html>// page.tsx
<h1 className={`${playfair.className} text-4xl`}>My Store</h1>
<p className="text-lg">Best products, best prices</p>9. Final Checklist
- ✅ Used next/font
- ✅ Defined subsets
- ✅ Used variable for Tailwind
- ✅ Fonts in fonts.ts
- ✅ Used display: 'swap'
- ✅ CLS = 0
Written & researched by Dr. Shahin Siami