惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

V
Visual Studio Blog
爱范儿
爱范儿
GbyAI
GbyAI
博客园 - 叶小钗
Last Week in AI
Last Week in AI
Jina AI
Jina AI
Microsoft Security Blog
Microsoft Security Blog
云风的 BLOG
云风的 BLOG
C
Check Point Blog
H
Help Net Security
P
Proofpoint News Feed
酷 壳 – CoolShell
酷 壳 – CoolShell
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
大猫的无限游戏
大猫的无限游戏
H
Hackread – Cybersecurity News, Data Breaches, AI and More
B
Blog RSS Feed
Y
Y Combinator Blog
U
Unit 42
T
Tailwind CSS Blog
MyScale Blog
MyScale Blog
N
Netflix TechBlog - Medium
S
SegmentFault 最新的问题
J
Java Code Geeks
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知

DEV Community

Authentication Security Deep Dive: From Brute Force to Salted Hashing (With Java Examples) Why AI Systems Don’t Fail — They Drift Spilling beans for how i learn for exam😁"Reinforcement Learning Cheat Sheet" I Replaced Chrome with Safari for AI Browser Automation. Here's What Broke (and What Finally Worked) How Python Borrows Other People's Work The $40 Architecture: Processing 1 Billion API Requests with 99.99% Uptime Vibe Coding: A Workflow Guide (From Zero to SaaS) Most webhook security guides protect the wrong side. The scary part is delivery. Headless CMS for TanStack Start: Build a Blog with Cosmic EU Age Verification App "Hacked in 2 Minutes" — What Actually Happened Comfy Cloud’s delete function does not actually remove files Running AI Models on GPU Cloud Servers: A Beginner Guide Event-driven media intelligence with AWS Step Functions and Bedrock I scored 500 AI prompts across 8 quality dimensions — here's what broke How to Call Google Gemini API from Next.js (Free Tier, No Backend Needed) The Portal Protocol: Reclaiming Human Connection in the Age of AI How to Fix Your Team's Scattered Knowledge Problem With a Self-Hosted Forum Intro to tc Cloud Functors: A Graph-First Mental Model for the Modern Cloud Designing Multi-Tenant Backends With Both Ownership and Team Access I Built a Neumorphic CSS Library with 77+ Components — Here's What I Learned PostgreSQL Performance Optimization: Why Connection Pooling Is Critical at Scale Cómo construí un SaaS multi-rubro para gestionar expensas en Argentina con FastAPI + Vue 3 🚀 I Built an Ethical Hacking Scanner Tool – Open Source Project I Replaced /usage and /context in Claude Code With a Single Statusline A Pythonic Way to Handle Emails (IMAP/SMTP) with Auto-Discovery and AI-Ready Design I Collected 8.9 Million Polymarket Price Points — Here's What I Found About How Markets Really Move EcoTrack AI — Carbon Footprint Tracker & Dashboard Everyone's Using AI. No One Agrees How. 5 self-hosted ebook managers worth trying in 2026 Building Your First AI Agent with LangChain: From Chatbot to Autonomous Assistant
Adding custom fonts to a Next.js app without the layout s...
Zerrin Arslan · 2026-06-16 · via DEV Community

Zerrin Arslan

If you've used Next.js in the last couple of years you've probably reached for next/font. It's genuinely great — but I still see custom fonts done in ways that tank the Lighthouse score or make the page jump around on load. Here's how I actually wire up fonts in a Next.js app now, and the one thing that quietly fixes most of the layout shift.

Google fonts: next/font/google already self-hosts

First, a thing a lot of people miss: next/font/google doesn't load anything from Google's servers at runtime. At build time Next downloads the font files and serves them from your own origin. So you get the self-hosting win (no third-party request on the critical path) for free:

import { Inter } from "next/font/google";

const inter = Inter({ subsets: ["latin"], display: "swap" });

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

That subsets: ["latin"] line matters — it subsets the file so you're not shipping glyphs for languages you don't use.

Custom / paid fonts: next/font/local

For a font that isn't on Google Fonts — a brand font, a freebie you downloaded, whatever — use next/font/local and point it at a WOFF2 in your project:

import localFont from "next/font/local";

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

Then expose it as a CSS variable and use it wherever:

<html className={display.variable}>

.heading { font-family: var(--font-display), sans-serif; }

If your font is a .ttf/.otf, convert it to WOFF2 first — smaller and supported everywhere. I usually just drop it into FontBoxDL's webfont generator (browser-based, no install) and grab the WOFF2 back. And if you're still hunting for the font itself, the free library has a pile of them.

The thing that actually fixes layout shift

Here's the part people skip. Even with display: swap, when the real font swaps in it usually has different metrics than the fallback — so text reflows and your CLS spikes. next/font can fix this automatically if you give it a fallback to match against:

const display = localFont({
  src: "./fonts/MyFont-Regular.woff2",
  display: "swap",
  fallback: ["system-ui", "arial"],
  adjustFontFallback: "Arial", // generates a size-adjusted @font-face for the fallback
});

adjustFontFallback makes Next emit a fallback @font-face with size-adjust/ascent-override tuned so the fallback occupies almost exactly the same space as your real font. The swap becomes nearly invisible. This one prop has done more for my CLS numbers than anything else.

Quick gotchas

  • Don't import a font inside a component that re-renders. Declare it at module scope (top of the file), once. Importing it in the render path defeats the optimization.
  • variable vs className: use className if it's your single global font; use variable when you want multiple fonts available as CSS custom properties.
  • Preload is automatic for fonts used on the route — you don't need a manual <link rel="preload"> like you would in a plain HTML setup.

TL... actually, no TL;DR

Use next/font/google for Google fonts (it self-hosts), next/font/local for everything else, ship WOFF2, and set adjustFontFallback so the swap doesn't shove your layout around. Takes ten minutes and your Core Web Vitals will thank you.

What's your go-to for custom fonts in Next — next/font/local, or do you still hand-roll the @font-face?