- Next.js
- Asset Optimization & Performance
- Zero-CLS Font Optimization with next/font
Zero-CLS Font Optimization with next/font
next/font automatically hosts Google Fonts and custom fonts locally at build time, eliminating external network requests to Google servers for GDPR compliance. It injects automatic fallback CSS font-adjust metrics (size-adjust, ascent-override, descent-override) that match the fallback system font geometry to the custom font, eliminating Cumulative Layout Shift (CLS).
Learning Objectives
Integrate Google and local fonts using next/font/google and next/font/local.
Explain how font metric overrides eliminate Cumulative Layout Shift (CLS).
Comply with GDPR by eliminating third-party external requests to Google font servers.
Apply font variables across Tailwind CSS and CSS modules.
Prerequisites & Background Knowledge
Why Interviewers Care
Crucial for achieving 100/100 Lighthouse performance scores and ensuring European privacy compliance.
The Challenge
How does next/font achieve zero Cumulative Layout Shift (CLS)? Implement both a Google variable font and a custom local font with Tailwind CSS integration.
Code Architecture & Implementation
1// app/layout.tsx2import { Inter } from 'next/font/google';3import localFont from 'next/font/local';4import './globals.css';56// 1. Google Font: Downloaded and self-hosted locally at build time!7const inter = Inter({8 subsets: ['latin'],9 display: 'swap',10 variable: '--font-inter', // CSS Variable for Tailwind11});1213// 2. Local Font with multiple weights:14const geistSans = localFont({15 src: [16 { path: './fonts/Geist-Regular.woff2', weight: '400', style: 'normal' },17 { path: './fonts/Geist-Bold.woff2', weight: '700', style: 'normal' },18 ],19 variable: '--font-geist-sans',20 display: 'swap',21});2223export default function RootLayout({ children }: { children: React.ReactNode }) {24 return (25 <html lang="en" className={`${inter.variable} ${geistSans.variable}`}>26 <body className="font-sans antialiased">{children}</body>27 </html>28 );29}
Architectural Explanation
When browsers load external web fonts, they either hide text until the font loads (Flash of Invisible Text - FOIT) or show a fallback system font that swaps when the custom font arrives (Flash of Unstyled Text - FOUT). Because Arial and Inter have different letter widths and heights, swapping them pushes surrounding layout elements down, triggering CLS. next/font computes the exact glyph bounding box differences and generates a custom fallback @font-face rule using size-adjust and ascent-override. The fallback font occupies the EXACT same pixel height and width as Inter, achieving a 0.000 CLS score.
Common Mistakes & Anti-Patterns
Using `<link rel="stylesheet" href="https://fonts.googleapis.com/...">`, making external requests that violate GDPR and cause CLS.
Loading 10 distinct font weights instead of utilizing modern variable fonts.
Instantiating font objects inside component functions instead of module scope.
Interview Follow-Up Traps
The interviewer asks: "Do requests to Google Fonts via next/font occur on every client page visit?" No! Google Fonts are downloaded by the build server once during `next build` and packaged as static woff2 files served from your own domain.
Frequently Asked Questions
Can you subset fonts to include only specific characters?
Yes, via the `subsets: ["latin"]` option to strip unused Cyrillic/Greek glyphs and save bandwidth.
Is next/font compatible with CSS Modules?
Yes! You can apply `className={inter.className}` directly to any element.
