Back to Blog
Lesson 33 of the Next.js: Build Full-Stack Apps with the App Router course
Next.jsAugust 20, 20264 min read

Using Font Optimization: Next.js Performance Guide

Learn to use next/font for automatic self-hosting of Google Fonts. Stop layout shifts and boost performance by mastering font optimization in Next.js.

Next.jsperformanceweb-developmentfontsoptimizationfrontend
Black and white image of 'Never Give Up' decal on a Hyundai car.

Previously in this course, we explored Advanced Tailwind Configurations to build a scalable design language. Now, we'll refine that design by implementing performant typography.

Custom fonts are often the silent killers of web performance. If not handled correctly, they cause Flash of Invisible Text (FOIT) or, worse, Flash of Unstyled Text (FOUT), both of which trigger Cumulative Layout Shift (CLS). In Next.js, the next/font module solves this by automatically self-hosting Google Fonts at build time, eliminating external network requests during page load.

The Principles of Font Optimization

When you load a font from an external CDN like Google Fonts, the browser must perform a DNS lookup, establish a connection, and download the CSS before it even begins fetching the font files. This adds significant latency.

next/font changes this by:

  1. Self-hosting: It downloads font files at build time and bundles them with your project.
  2. Zero Layout Shifts: It uses size-adjust and CSS fallback fonts to match the dimensions of your custom font, ensuring no layout jumps occur while the font loads.
  3. No External Requests: Since the fonts are part of your deployment, there are no third-party requests to block or track users.

Configuring next/font

Detailed view of different font styles printed on paper, showcasing typography.

To get started, we'll add a Google Font to our root layout. Open app/layout.js (which we first touched in Building the Root Layout) and import your desired font.

JAVASCRIPT
import { Inter } from CE9178">'next/font/google';

const inter = Inter({
  subsets: [CE9178">'latin'],
  display: CE9178">'swap',
  variable: CE9178">'--font-inter',
});

export default function RootLayout({ children }) {
  return (
    <html lang="en" className={inter.variable}>
      <body className="font-sans">{children}</body>
    </html>
  );
}

Key Configuration Options

  • subsets: Always define the subsets you need (e.g., ['latin']). This prevents unnecessary glyphs from being downloaded, drastically reducing file size.
  • variable: By providing a CSS variable name, you can easily access this font within your Tailwind configuration.
  • display: 'swap': This tells the browser to use a system font immediately while the custom font downloads, which is essential for Font Loading Strategy and eliminating FOIT.

Integrating with Tailwind CSS

To make this font available globally in our project, we map the CSS variable to our tailwind.config.js.

JAVASCRIPT
// tailwind.config.js
module.exports = {
  theme: {
    extend: {
      fontFamily: {
        sans: [CE9178">'var(--font-inter)', CE9178">'sans-serif'],
      },
    },
  },
};

By setting font-sans to use our custom variable, any element using the standard Tailwind font-sans class will now automatically use the optimized Inter font. This is a massive improvement over manual @import statements, which often contribute to CLS and poor Core Web Vitals.

Hands-on Exercise

  1. Identify a font: Pick a font from Google Fonts.
  2. Implementation: Import it into your layout.js using next/font/google.
  3. Apply: Assign the generated variable to the <html> or <body> tag.
  4. Verify: Open your browser's Network tab. Reload the page and filter by "Font." You should see local requests to your own domain (e.g., _next/static/media/...) rather than fonts.gstatic.com.

Common Pitfalls

Close-up of a triangular warning sign indicating a slippery surface, fixed to a wooden post.

  • Over-importing: Importing every weight and style (italic, 900, 100, etc.) significantly increases your JS bundle size. Only import the weights you actually use in your design system.
  • Forgetting display: 'swap': Without this, the browser might hide your text entirely until the font file is fully downloaded, causing a poor user experience.
  • Mixing next/font with manual @import: Never mix these. If you use next/font, remove any Google Font <link> tags or CSS @import rules from your project to avoid double-loading.

Frequently Asked Questions

Does next/font work with local font files? Yes. You can use localFont from next/font/local to import .woff2 files stored in your public/fonts directory.

How does this affect my LCP (Largest Contentful Paint)? Because next/font self-hosts the assets, the browser doesn't have to wait for external API handshakes. This usually results in a faster LCP, especially when combined with proper critical font optimization.

Can I use multiple fonts? Absolutely. You can import as many as you need, but keep an eye on your performance metrics—each font adds to your total page weight.

Recap

Team members presenting a project in a modern office setting with a focus on collaboration.

We've successfully moved away from external font dependencies in favor of next/font. By self-hosting our assets and mapping them to CSS variables, we've improved our site's loading speed, eliminated layout shifts, and deepened our integration with Tailwind. These steps are foundational for achieving high scores in Performance Auditing.

Up next: We will explore how to use Middleware to intercept and transform requests before they reach our pages.

Similar Posts