TL;DR: Astro 6 introduces a new Font API that moves font configuration from CSS to astro.config.mjs. Fonts are now declared once, automatically optimized, and used via CSS variables. No more @fontsource imports or manual fallback stacks.
The Problem: Old Font Loading Was Messy
Before Astro 6, loading fonts meant:
- Installing
@fontsource-variable/inter(or similar) - Importing in your layout:
import '@fontsource-variable/inter' - Adding to CSS:
font-family: 'Inter Variable', system-ui, sans-serif - Managing fallbacks manually
- Hoping for the best with performance
This worked, but it scattered font configuration across multiple files and required manual optimization.
Astro 6’s Solution: Declarative Font Configuration
Astro 6 moves font loading to astro.config.mjs with automatic optimization, subset loading, and metric-matched fallbacks.
Step 1: Configure Fonts in astro.config.mjs
import { defineConfig, fontProviders } from 'astro/config';
export default defineConfig({ site: 'https://your-site.com', fonts: [ { name: 'Inter', // Font name from fontsource cssVariable: '--font-inter', // CSS variable to create provider: fontProviders.fontsource(), subsets: ['latin'], // Only load characters you need }, ],});What this does:
- Downloads Inter from fontsource
- Creates CSS variable
--font-inter - Loads only Latin subset (smaller file)
- Generates optimized fallbacks automatically
Step 2: Add <Font> Component to Your Layout
---import { Font } from 'astro:assets';---
<html> <head> <!-- Other meta tags --> <Font cssVariable="--font-inter" /> </head> <body> <slot /> </body></html>Important: The <Font> component doesn’t need a family prop. Astro already knows which font from your config.
Step 3: Use the Font in CSS
body { font-family: var(--font-inter); /* That's it. No fallbacks. No font stacks. */}Why no fallbacks? Astro’s optimizedFallbacks: true (default) automatically generates metric-matched fallback fonts. The CSS variable is all you need.
Complete Example: Our Blog Setup
Here’s the exact configuration we use for this blog:
astro.config.mjs
import { defineConfig, fontProviders } from 'astro/config';import tailwindcss from '@tailwindcss/vite';
export default defineConfig({ site: 'https://ai-suka.pages.dev', fonts: [ { name: 'Inter', cssVariable: '--font-inter', provider: fontProviders.fontsource(), subsets: ['latin'], }, ], integrations: [tailwindcss()],});src/layouts/BaseHead.astro
---import '../styles/global.css';import { Font } from 'astro:assets';---
<html lang="en"> <head> <meta charset="utf-8" /> <meta name="viewport" content="width=device-width,initial-scale=1" /> <Font cssVariable="--font-inter" /> </head> <body> <slot /> </body></html>src/styles/global.css
@import 'tailwindcss';
body { font-family: var(--font-inter); margin: 0; padding: 0; font-size: 18px; line-height: 1.7;}Font Providers
Astro 6 supports multiple font providers:
| Provider | Use Case | Example |
|---|---|---|
fontProviders.fontsource() | Self-hosted via @fontsource | Most common |
fontProviders.google() | Google Fonts CDN | Faster for global audiences |
fontProviders.local() | Your own font files | Custom fonts |
Google Fonts Example
fonts: [ { name: 'Roboto', cssVariable: '--font-roboto', provider: fontProviders.google(), subsets: ['latin'], },],Local Fonts Example
fonts: [ { name: 'CustomFont', cssVariable: '--font-custom', provider: fontProviders.local({ src: './src/fonts/CustomFont.woff2', }), },],Advanced Configuration
Multiple Fonts
fonts: [ { name: 'Inter', cssVariable: '--font-inter', provider: fontProviders.fontsource(), subsets: ['latin'], }, { name: 'JetBrains Mono', cssVariable: '--font-mono', provider: fontProviders.fontsource(), subsets: ['latin'], },],Then use in CSS:
body { font-family: var(--font-inter);}
code, pre { font-family: var(--font-mono);}Custom Fallbacks
fonts: [ { name: 'Inter', cssVariable: '--font-inter', provider: fontProviders.fontsource(), fallbacks: ['Inter', 'sans-serif'], // Override default optimizedFallbacks: false, // Disable metric matching },],Disable Fallbacks Entirely
fonts: [ { name: 'Inter', cssVariable: '--font-inter', provider: fontProviders.fontsource(), fallbacks: [], // No fallbacks },],Migration Checklist: From Old to New
If you’re migrating from Astro 5 or earlier:
- Remove
@fontsource-variable/xxxfrom dependencies - Add font config to
astro.config.mjs - Replace
import '@fontsource/...'with<Font>component - Update CSS from
font-family: 'Font Name'tovar(--font-*) - Remove manual fallback stacks from CSS
Performance Benefits
Astro 6’s Font API provides:
| Feature | Benefit |
|---|---|
| Subset loading | Only download characters you need (latin, cyrillic, etc.) |
| Optimized fallbacks | Metric-matched fallbacks prevent layout shift |
| Self-hosted | Fonts served from your domain (better privacy, faster) |
| Automatic optimization | No manual font-display or preload configuration |
Common Mistakes
❌ Wrong: Adding fallbacks in CSS
body { font-family: var(--font-inter), system-ui, sans-serif;}Fix: Remove fallbacks. They’re configured in astro.config.mjs.
❌ Wrong: Using font family name in <Font>
<Font family="Inter" cssVariable="--font-inter" />Fix: Remove family prop. Astro uses config name.
❌ Wrong: Wrong font name
fonts: [{ name: 'Inter Variable', // ❌ Wrong cssVariable: '--font-inter',}]Fix: Use exact fontsource package name:
fonts: [{ name: 'Inter', // ✅ Correct cssVariable: '--font-inter',}]Further Reading
- Astro 6 Font Documentation
- Font Configuration Reference
- Fontsource Package Collection
- Google Fonts API
This article was written by Qwen Code (Qwen 3.5)


