Zero-config font optimization for Vite - auto-detect fonts from CSS, download, and self-host with fallback metrics
npm install vite-fontsZero-config font optimization for Vite - auto-detect fonts from CSS, download, and self-host with fallback metrics.
Similar to @nuxt/fonts but for any Vite project (Vue, React, Svelte, etc.).
- Zero Configuration - Automatically detects font-family declarations in your CSS
- Multiple Providers - Bunny Fonts, Fontsource, local fonts (Google Fonts opt-in)
- Self-Hosting - Downloads and bundles fonts at build time for privacy and performance
- Fallback Metrics - Generates adjusted fallback fonts to reduce CLS (Cumulative Layout Shift)
- Caching - Persistent file cache for fast rebuilds and offline development
- Dev Server Support - Fonts work seamlessly in development mode
- Blazing Fast - Built with Rust-based tools (LightningCSS, oxlint, tsgo)
``bash`
npm install vite-fontsor
pnpm add vite-fontsor
bun add vite-fonts
`ts
// vite.config.ts
import { defineConfig } from 'vite'
import fonts from 'vite-fonts'
export default defineConfig({
plugins: [fonts()],
})
`
Then use fonts in your CSS as normal:
`css
body {
font-family: 'Inter', sans-serif;
}
code {
font-family: 'Fira Code', monospace;
}
`
The plugin will automatically:
1. Detect the font-family declarations@font-face
2. Resolve fonts from configured providers (Bunny, Fontsource, local)
3. Download the font files
4. Generate and inject rules
5. Create fallback font metrics to reduce layout shift
`ts
// vite.config.ts
import { defineConfig } from 'vite'
import fonts from 'vite-fonts'
export default defineConfig({
plugins: [
fonts({
// Default options for all fonts
defaults: {
weights: [400, 700],
styles: ['normal', 'italic'],
subsets: ['latin', 'latin-ext'],
display: 'swap',
},
// Explicitly configure specific fonts
families: {
'Inter': {
weights: [400, 500, 600, 700],
styles: ['normal'],
},
'Fira Code': {
weights: [400, 700],
provider: 'fontsource',
},
},
// Provider configuration
providers: {
bunny: true, // Bunny Fonts (privacy-focused)
fontsource: true, // Fontsource (npm packages)
google: false, // Google Fonts (opt-in)
local: true, // Local fonts in public/
},
// Generate fallback font metrics (reduces CLS)
fallbacks: true,
// Caching
cache: true,
cacheDir: 'node_modules/.cache/vite-fonts',
// Output
assetsDir: 'fonts',
inject: 'inline', // 'inline' | 'external'
// Debug logging
debug: false,
}),
],
})
`
| Option | Type | Default | Description |
|--------|------|---------|-------------|
| defaults | object | See below | Default font options |defaults.weights
| | number[] | [400, 700] | Font weights to download |defaults.styles
| | string[] | ['normal'] | Font styles to download |defaults.subsets
| | string[] | ['latin'] | Unicode subsets |defaults.display
| | string | 'swap' | Font display strategy |families
| | object | {} | Per-font configuration |providers
| | object | See below | Provider configuration |providers.bunny
| | boolean | true | Enable Bunny Fonts |providers.fontsource
| | boolean | true | Enable Fontsource |providers.google
| | boolean | false | Enable Google Fonts |providers.local
| | boolean\|object | true | Enable local fonts |fallbacks
| | boolean | true | Generate fallback metrics |cache
| | boolean | true | Enable font caching |cacheDir
| | string | node_modules/.cache/vite-fonts | Cache directory |assetsDir
| | string | 'fonts' | Output directory for fonts |inject
| | string | 'inline' | CSS injection method |debug
| | boolean | false | Enable debug logging |
1. CSS Parsing - Uses LightningCSS (100x faster than PostCSS) to parse your CSS and extract font-family declarations.
2. Font Resolution - Uses unifont (same library as @nuxt/fonts) to resolve fonts from multiple providers.
3. Downloading - Font files are downloaded and cached using unstorage for fast rebuilds.
4. Fallback Generation - Uses fontaine to generate adjusted fallback @font-face rules that reduce Cumulative Layout Shift (CLS).
5. Injection - @font-face rules are injected into your HTML, either as an inline