
Optimize Web Performance with Nuxt Fontaine
In web performance work, we often obsess over backend optimizations and miss easy, high-impact wins on the frontend. One such win is font rendering. In a previous article I covered using PartyTown to offload third-party scripts; today we’ll focus on fonts—specifically, font metric fallbacks—and how to implement them in Nuxt with Nuxt Fontaine.
What Is Nuxt Fontaine?
Nuxt Fontaine is a Nuxt 3 module that automatically creates local fallback faces with font metric overrides to cut Cumulative Layout Shift (CLS)—using pure CSS, with zero runtime.
The underlying library, fontaine
, also works outside Nuxt, giving you broader flexibility.
Key Benefits
- Reduce CLS using local font fallbacks with crafted metrics.
- Automatically generates font metrics and fallback rules.
- No runtime overhead—all logic resolved via CSS.
On the module’s playground, enabling Fontaine drastically improves CLS (e.g., from 0.34 → 0.013) and boosts performance.
Installation
Use the nuxi
one-liner—or choose your package manager:
# Recommended
npx nuxi@latest module add fontaine
Or manually:
# pnpm
pnpm add -D @nuxtjs/fontaine
# yarn
yarn add -D @nuxtjs/fontaine
# npm
npm install -D @nuxtjs/fontaine
Basic Usage (Nuxt 3/4)
Add the module to your nuxt.config.ts:
// nuxt.config.ts
export default defineNuxtConfig({
modules: ['@nuxtjs/fontaine'],
// Optional: declare fonts not defined via @font-face (e.g., Google Fonts)
// fontMetrics: {
// fonts: ['Inter', { family: 'Some Custom Font', src: '/fonts/custom.woff2' }],
// },
})
That’s it—Fontaine handles the rest.
Tailwind CSS Integration
If you’re using Tailwind and define a custom font, add the fallback alias:
// tailwind.config.ts
import type { Config } from 'tailwindcss'
import { fontFamily } from 'tailwindcss/defaultTheme'
export default <Partial<Config>>{
theme: {
extend: {
fontFamily: {
sans: ['Roboto', 'Roboto fallback', ...fontFamily.sans],
},
},
},
}
This ensures Tailwind utilities include the correct fallback.
How Fontaine Works
Fontaine scans your @font-face definitions and generates matching fallback rules with correct metrics. For example:
/* Your definition */
@font-face {
font-family: 'Roboto';
font-display: swap;
src: url('/fonts/Roboto.woff2') format('woff2'),
url('/fonts/Roboto.woff') format('woff');
font-weight: 700;
}
/* Generated fallback */
@font-face {
font-family: 'Roboto fallback';
src: local('Segoe UI'), local('Roboto'), local('Helvetica Neue'),
local('Arial'), local('Noto Sans');
ascent-override: 92.7734375%;
descent-override: 24.4140625%;
line-gap-override: 0%;
}
Then Vue or Nuxt automatically updates your font stacks:
:root {
font-family: 'Roboto'; /* becomes */
font-family: 'Roboto', 'Roboto fallback';
}
Tip: Inline Critical Styles for Zero CLS
Fontaine eliminates font-related CLS, but stylesheet loading may still cause shifts. To fully avoid this, inline your CSS during SSR:
// nuxt.config.ts (Nuxt 4)
export default defineNuxtConfig({
modules: ['@nuxtjs/fontaine'],
inlineStyles: true, // inline styles during SSR for layout stability
})
This aligns with the approach behind the PR aiming to inline all CSS in Nuxt.
Complementary Tool: Nuxt Fonts
To optimize font delivery (subsetting, preloading, hosting), consider using @nuxt/fonts. It includes Fontaine-powered metrics optimization plus font loading strategies.
Summary & Best Practices
- Use font-display: swap in your @font-face declarations for fast rendering.
- Let Fontaine generate the fallback alias—avoid manually naming overlaps.
- Declare fonts via fontMetrics.fonts if they’re not defined in CSS (e.g., Google Fonts).
- Measure improvements using Lighthouse—Fontaine demonstrably boosts scores.
Beyond Nuxt
Want metric‑matched fallbacks outside Nuxt? Use the fontaine library in pipelines (e.g. Vite, Webpack) suitable for Astro, Next.js, and beyond.
By combining Nuxt Fontaine, style inlining, and possibly Nuxt Fonts, you’ll achieve smoother, shift-free font loading—and a significantly better user experience.