# Font Optimization Use `next/font` for automatic font optimization with zero layout shift. ## Google Fonts ```tsx // app/layout.tsx import { Inter } from 'next/font/google' const inter = Inter({ subsets: ['latin'] }) export default function RootLayout({ children }: { children: React.ReactNode }) { return (
{children} ) } ``` ## Multiple Fonts ```tsx import { Inter, Roboto_Mono } from 'next/font/google' const inter = Inter({ subsets: ['latin'], variable: '--font-inter', }) const robotoMono = Roboto_Mono({ subsets: ['latin'], variable: '--font-roboto-mono', }) export default function RootLayout({ children }: { children: React.ReactNode }) { return ( {children} ) } ``` Use in CSS: ```css body { font-family: var(--font-inter); } code { font-family: var(--font-roboto-mono); } ``` ## Font Weights and Styles ```tsx // Single weight const inter = Inter({ subsets: ['latin'], weight: '400', }) // Multiple weights const inter = Inter({ subsets: ['latin'], weight: ['400', '500', '700'], }) // Variable font (recommended) - includes all weights const inter = Inter({ subsets: ['latin'], // No weight needed - variable fonts support all weights }) // With italic const inter = Inter({ subsets: ['latin'], style: ['normal', 'italic'], }) ``` ## Local Fonts ```tsx import localFont from 'next/font/local' const myFont = localFont({ src: './fonts/MyFont.woff2', }) // Multiple files for different weights const myFont = localFont({ src: [ { path: './fonts/MyFont-Regular.woff2', weight: '400', style: 'normal', }, { path: './fonts/MyFont-Bold.woff2', weight: '700', style: 'normal', }, ], }) // Variable font const myFont = localFont({ src: './fonts/MyFont-Variable.woff2', variable: '--font-my-font', }) ``` ## Tailwind CSS Integration ```tsx // app/layout.tsx import { Inter } from 'next/font/google' const inter = Inter({ subsets: ['latin'], variable: '--font-inter', }) export default function RootLayout({ children }) { return ( {children} ) } ``` ```js // tailwind.config.js module.exports = { theme: { extend: { fontFamily: { sans: ['var(--font-inter)'], }, }, }, } ``` ## Preloading Subsets Only load needed character subsets: ```tsx // Latin only (most common) const inter = Inter({ subsets: ['latin'] }) // Multiple subsets const inter = Inter({ subsets: ['latin', 'latin-ext', 'cyrillic'] }) ``` ## Display Strategy Control font loading behavior: ```tsx const inter = Inter({ subsets: ['latin'], display: 'swap', // Default - shows fallback, swaps when loaded }) // Options: // 'auto' - browser decides // 'block' - short block period, then swap // 'swap' - immediate fallback, swap when ready (recommended) // 'fallback' - short block, short swap, then fallback // 'optional' - short block, no swap (use if font is optional) ``` ## Don't Use Manual Font Links Always use `next/font` instead of `` tags for Google Fonts. ```tsx // Bad: Manual link tag (blocks rendering, no optimization) // Bad: Missing display and preconnect // Good: Use next/font (self-hosted, zero layout shift) import { Inter } from 'next/font/google' const inter = Inter({ subsets: ['latin'] }) ``` ## Common Mistakes ```tsx // Bad: Importing font in every component // components/Button.tsx import { Inter } from 'next/font/google' const inter = Inter({ subsets: ['latin'] }) // Creates new instance each time! // Good: Import once in layout, use CSS variable // app/layout.tsx const inter = Inter({ subsets: ['latin'], variable: '--font-inter' }) // Bad: Using @import in CSS (blocks rendering) /* globals.css */ @import url('https://fonts.googleapis.com/css2?family=Inter'); // Good: Use next/font (self-hosted, no network request) import { Inter } from 'next/font/google' // Bad: Loading all weights when only using a few const inter = Inter({ subsets: ['latin'] }) // Loads all weights // Good: Specify only needed weights (for non-variable fonts) const inter = Inter({ subsets: ['latin'], weight: ['400', '700'] }) // Bad: Missing subset - loads all characters const inter = Inter({}) // Good: Always specify subset const inter = Inter({ subsets: ['latin'] }) ``` ## Font in Specific Components ```tsx // For component-specific fonts, export from a shared file // lib/fonts.ts import { Inter, Playfair_Display } from 'next/font/google' export const inter = Inter({ subsets: ['latin'], variable: '--font-inter' }) export const playfair = Playfair_Display({ subsets: ['latin'], variable: '--font-playfair' }) // components/Heading.tsx import { playfair } from '@/lib/fonts' export function Heading({ children }) { return