Next.js Font Optimization: Zero Layout Shift - By Sourav Mishra (@souravvmishra)

Eliminate Cumulative Layout Shift (CLS) with next/font. Learn how to use Google Fonts and variable fonts efficiently in your Next.js application.

BySourav Mishra3 min read

In this guide, I, Sourav Mishra, explain how to use next/font to achieve perfect Core Web Vitals scores by eliminating font-related layout shifts.

Fonts are often the heaviest assets on a page. If not loaded correctly, they cause "FOIT" (Flash of Invisible Text) or "FOUT" (Flash of Unstyled Text), leading to jarring layout shifts (CLS) that hurt both user experience and SEO.

Why next/font?

The next/font package (built into Next.js) solves this by:

  1. Self-hosting automatically: No requests to Google servers at runtime (privacy friendly).
  2. Zero Layout Shift: It uses a fallback font that perfectly matches the dimensions of your custom font until it loads.
  3. Preloading: Critical fonts are injected into the initial HTML.

1. Using Google Fonts

Import the font you need from next/font/google. Use Variable Fonts whenever possible to reduce network requests (one file for all weights).

// app/layout.tsx
import { Inter } from "next/font/google";
import "./globals.css";

// 1. Configure the font
const inter = Inter({ 
  subsets: ["latin"],
  display: "swap",
  variable: "--font-inter", // Define a CSS variable
});

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

2. Integration with Tailwind CSS

To use this font in Tailwind, update your config to listen to the CSS variable we just created (--font-inter).

// tailwind.config.ts
import { fontFamily } from "tailwindcss/defaultTheme";

export default {
  theme: {
    extend: {
      fontFamily: {
        // Adds 'font-sans' class that uses Inter, with fallbacks
        sans: ["var(--font-inter)", ...fontFamily.sans],
      },
    },
  },
};

Now, font-sans (the default) uses optimized Inter.

3. Using Local Fonts

Ideally, you use Google Fonts. But for custom branding, use next/font/local.

import localFont from "next/font/local";

const myFont = localFont({
  src: [
    {
      path: "./fonts/MyFont-Regular.woff2",
      weight: "400",
      style: "normal",
    },
    {
      path: "./fonts/MyFont-Bold.woff2",
      weight: "700",
      style: "normal",
    },
  ],
  variable: "--font-brand",
});

Best Practices

  • Subsets: Always specify subsets: ["latin"] to avoid downloading characters (like Cyrillic) you don't use.
  • Preload: By default, subsets are preloaded. Don't disable this unless you have a specific reason.
  • Variable Fonts: Stick to variable fonts to avoid downloading 10 different files for Bold, Italic, ExtraBold, etc.

Conclusion

Font optimization is a "set it and forget it" feature in Next.js that yields massive performance wins.

If you're interested in more performance tips, check out React Suspense Guide.

FAQ

Q: Does this work with Styled Components? Yes, you can pass the inter.className directly to any component or inject the variable into your global styles.

Q: Can I use multiple fonts? Yes, just create multiple instances (e.g., inter and playfair) and pass both variables to your html tag:

<html className={`${inter.variable} ${playfair.variable}`}>

This guide was written by Sourav Mishra, focusing on high-performance web vitals.

Share this post

Cover image for Next.js Font Optimization: Zero Layout Shift

You might also like

See all