Load fonts without shift

Use next/font, preload needed weights, match fallback metrics.

From nextjs-pagespeed.

The swap shifts the page

Press Load web font and watch the button.

Plain fallbackBad

September close is ready

Bank feeds are reconciled through the 30th. Three vendor bills still need a receipt, and the prepaid insurance schedule posted its monthly entry. Review the accruals and the two open reconciling items before you lock the period.

Review entries

Locks the period for everyone

–CLS –
Matched fallbackGood

September close is ready

Bank feeds are reconciled through the 30th. Three vendor bills still need a receipt, and the prepaid insurance schedule posted its monthly entry. Review the accruals and the two open reconciling items before you lock the period.

Review entries

Locks the period for everyone

–CLS –
import { Geist } from "next/font/google";

const geist = Geist({
  subsets: ["latin"],
  display: "swap",
  adjustFontFallback: true,
  variable: "--font-sans",
});

@font-face {
  font-family: "Geist Fallback";
  src: local("Arial");
  size-adjust: 105.24%;
  ascent-override: 95.50%;
  descent-override: 28.03%;
  line-gap-override: 0.00%;
}

Overlay the two renderings

Drag size-adjust until red covers black.

Geist Arial

 
@font-face {
  font-family: "Geist Fallback";
  src: local("Arial");
  size-adjust: 105.24%;
  ascent-override: 95.50%;
  descent-override: 28.03%;
  line-gap-override: 0.00%;
}

Extra weights delay the hero

Toggle weights and press Play. The hero needs 400 and 600.

Preload
Waterfall
Blank

Revenue up 12% this quarter

Driven by three new retainer clients.

Web font
const geist = Geist({ subsets: ["latin"], weight: ["400", "600"] });
const geistMono = Geist_Mono({ subsets: ["latin"], preload: false });

Why it matters, pros and cons

Why it matters

With swap the fallback paints first; mismatched metrics reflow at the swap.

Pros

  • Self-hosted: no third-party request.
  • Metric overrides computed at build time.
  • Text shows first and stays put.

Cons

  • Matches average width; some lines still rebreak.
  • Synthesized bold in the fallback matches less well.
  • A system font stack costs zero bytes.