๐Ÿ“Š

Core Web Vitals & Fonts

How fonts affect LCP, CLS, and INP โ€” and exactly how to optimize them for better Google rankings and faster page loads.

๐Ÿ“– 12 min read โ€ข Updated January 2025

Quick Answer

Fonts primarily affect LCP and CLS. To optimize: use font-display: swap to prevent invisible text (LCP), preload your primary font, subset to reduce file size, and use metric overrides to minimize layout shift (CLS). Self-hosting with WOFF2 format typically improves all metrics.

In This Guide

What Are Core Web Vitals?

Core Web Vitals are Google's metrics for measuring user experience. They're a ranking factor, meaning better scores can improve your search rankings. In 2024, Google replaced FID with INP as the third metric.

๐Ÿ–ผ๏ธ

LCP

Largest Contentful Paint
Target: < 2.5s Font Impact: High

If your largest element contains text, font loading directly delays LCP.

๐Ÿ“

CLS

Cumulative Layout Shift
Target: < 0.1 Font Impact: High

Font swapping causes layout shifts when fallback and web font have different metrics.

๐Ÿ‘†

INP

Interaction to Next Paint
Target: < 200ms Font Impact: Low

Fonts rarely affect INP directly, but blocking resources can delay interactivity.

How Fonts Affect Each Metric

๐Ÿ–ผ๏ธ Fonts & LCP (Largest Contentful Paint)

LCP measures when the largest visible element finishes rendering. If that element contains text (like a hero headline), it won't render until the font loads โ€” or until the browser decides to show fallback text.

The Problem: Invisible Text (FOIT)

Without font-display: swap, browsers hide text until fonts load. If your font takes 3 seconds, your LCP is at least 3 seconds โ€” failing the 2.5s threshold.

The Fix

  • Use font-display: swap โ€” shows fallback immediately
  • Preload your primary font to speed up delivery
  • Subset fonts to reduce download time
  • Self-host to eliminate third-party latency

๐Ÿ“ Fonts & CLS (Cumulative Layout Shift)

CLS measures visual stability. When your web font loads and replaces the fallback, differences in character widths can cause content to shift โ€” especially in headings and multi-line text.

The Problem: Font Swap Layout Shift

Arial and Inter have different character widths. When Inter loads and replaces Arial, a 3-line paragraph might become 4 lines, pushing everything below it down.

The Fix

  • Use CSS font metric overrides (size-adjust, ascent-override)
  • Choose fallback fonts that closely match your web font
  • Consider font-display: optional for non-critical fonts
  • Preload to minimize the swap window

๐Ÿ‘† Fonts & INP (Interaction to Next Paint)

INP measures responsiveness to user interactions. Fonts rarely affect INP directly, but there are edge cases to be aware of.

When Fonts Can Affect INP

  • Render-blocking font CSS delays interactivity
  • Synchronous font loading JavaScript blocks the main thread
  • Large font files compete for bandwidth with interactive elements

Step-by-Step Optimization

1

Use font-display: swap

Critical Impact

Shows fallback text immediately while the web font loads. Eliminates invisible text.

@font-face {
  font-family: 'Inter';
  src: url('/fonts/inter.woff2') format('woff2');
  font-display: swap;
}
2

Preload Critical Fonts

High Impact

Tell the browser to fetch your primary font early in the loading process.

<link rel="preload"
      href="/fonts/inter.woff2"
      as="font"
      type="font/woff2"
      crossorigin>
3

Subset Your Fonts

High Impact

Remove unused characters to reduce file size by 70-95%.

/* Before: 300KB (full Inter) */
/* After: 20KB (Latin subset) */
unicode-range: U+0000-00FF;
4

Use WOFF2 Format

Medium Impact

WOFF2 offers 30% better compression than WOFF with 98%+ browser support.

@font-face {
  font-family: 'Inter';
  src: url('/fonts/inter.woff2') format('woff2');
  /* No need for WOFF fallback in 2025 */
}
5

Self-Host Fonts

Medium Impact

Eliminate third-party requests. No DNS lookup or connection to Google Fonts.

/* Instead of: */
@import url('https://fonts.googleapis.com/...');

/* Use: */
@font-face {
  font-family: 'Inter';
  src: url('/fonts/inter.woff2') format('woff2');
}
6

Match Fallback Metrics

Medium Impact

Use size-adjust, ascent-override, and descent-override to match fallback to web font.

@font-face {
  font-family: 'Inter Fallback';
  src: local('Arial');
  ascent-override: 90%;
  descent-override: 22%;
  line-gap-override: 0%;
  size-adjust: 107%;
}

Measuring Font Impact

Chrome DevTools

  • Network tab โ†’ filter by "Font"
  • Performance tab โ†’ see font load timing
  • Lighthouse โ†’ runs full CWV audit

PageSpeed Insights

  • Real-world CWV data from Chrome users
  • Specific font-related warnings
  • "Ensure text remains visible" audit

Web Vitals Extension

  • Real-time CWV overlay
  • See layout shift as it happens
  • Identify which elements cause CLS

WebPageTest

  • Detailed waterfall showing font timing
  • Filmstrip view shows font swap visually
  • Test from different locations/connections

Common Mistakes to Avoid

โŒ Preloading Too Many Fonts

Only preload 1-2 critical fonts. Preloading everything defeats the purpose and delays other important resources.

โŒ Using font-display: block

This intentionally hides text while fonts load. Unless you have a very specific design requirement, use swap instead.

โŒ Loading Full Font Files

A full Inter font is 300KB+. Most sites only need Latin characters (~20KB). Always subset your fonts.

โŒ Forgetting crossorigin on Preload

Font preload links require crossorigin attribute, even for same-origin fonts. Without it, the font loads twice.

โŒ Using @import for Google Fonts

CSS @import is render-blocking and requires multiple round-trips. Use <link> tags or self-host instead.

Quick Optimization Checklist

  • โ˜ Added font-display: swap to all @font-face
  • โ˜ Preloading 1-2 critical fonts
  • โ˜ Using WOFF2 format only
  • โ˜ Fonts are subsetted
  • โ˜ Self-hosting (no Google Fonts CDN)
  • โ˜ Fallback font metrics matched

Related Guides

Optimize Your Fonts for Core Web Vitals

Sift makes font optimization easy. Subset, convert to WOFF2, and generate optimized CSS in seconds โ€” all in your browser.

Try Sift Free