👨‍🏫 The Mastering Nuxt 3 course is now completed!

Discover the course
fontaine

Automatically optimized font fallback based on font metrics

Nuxt Fontaine

npm versionnpm downloadsGithub ActionsCodecov

Font metric override implementation for Nuxt 3

Features

⚠️ @nuxtjs/fontaine is under active development. ⚠️

  • 💪 Reduces CLS by using local font fallbacks with crafted font metrics.
  • ✨ Generates font metrics and overrides automatically.
  • ⚡️ Pure CSS, zero runtime overhead.

On the playground project, enabling/disabling this module makes the following differences rendering /, with no customisation required:

BeforeAfter
CLS0.340.013
Performance8898

What's next

For best performance, you will need to inline all your CSS, not just the font-face override rules (which this module does automatically), or there will still be a layout shift when the stylesheet loads (which is why the number above is not zero).

This PR aims to bring that ability to Nuxt itself.

Installation

With pnpm

pnpm add -D @nuxtjs/fontaine

Or, with npm

npm install -D @nuxtjs/fontaine

Or, with yarn

yarn add -D @nuxtjs/fontaine

Usage

export default defineNuxtConfig({
modules: ['@nuxtjs/fontaine'],
// If you are using a Google font or you don't have a @font-face declaration
// for a font you're using, you can declare them here.
//
// In most cases this is not necessary.
//
// fontMetrics: {
// fonts: ['Inter', { family: 'Some Custom Font', src: '/path/to/custom/font.woff2' }],
// },
})

That's it!

How it works

Nuxt will scan your @font-face rules and generate fallback rules with the correct metrics. For example:

@font-face {
font-family: 'Roboto';
font-display: swap;
src: url('/fonts/Roboto.woff2') format('woff2'), url('/fonts/Roboto.woff') format('woff');
font-weight: 700;
}
/* This will be generated. */
@font-face {
font-family: 'Roboto override';
src: local('BlinkMacSystemFont'), 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, whenever you use font-family: 'Roboto', Nuxt will add the override to the font-family:

:root {
font-family: 'Roboto';
/* This becomes */
font-family: 'Roboto', 'Roboto override';
}

Using outside of Nuxt

The core of this module will work outside of Nuxt, and has been separated into a separate library: fontaine. Check it out!

💻 Development

  • Clone this repository
  • Enable Corepack using corepack enable (use npm i -g corepack for Node.js < 16.10)
  • Install dependencies using pnpm install
  • Stub module with pnpm dev:prepare
  • Run pnpm dev to start playground in development mode

Credits

This would not have been possible without:

License

Made with ❤️

Published under the MIT License.