Font Caching Strategies
Implement browser caching best practices for fonts. Configure Cache-Control headers, immutable caching, CDN strategies, and service worker caching for optimal repeat visit performance.
Key Takeaways
- • Set
max-age=31536000(1 year) for font files - • Use
immutabledirective to prevent revalidation - • Version fonts in filename for cache busting
- • CDN caching provides global edge distribution
In this article
Why Font Caching Matters
Font files rarely change, making them ideal candidates for aggressive caching. Properly cached fonts load instantly on repeat visits, eliminating font-related performance issues entirely.
Without Caching
- • Font re-downloaded every visit
- • 200-500ms added to each page load
- • Wasted bandwidth for users
- • Higher server costs
With Proper Caching
- • Instant font load from cache
- • Zero network requests
- • Works offline (service worker)
- • Reduced server load
Cache-Control Headers
The Cache-Control header tells browsers how to cache resources. For fonts, use aggressive caching with long expiration.
# Optimal font caching headers Cache-Control: public, max-age=31536000, immutable # Breakdown: # public - Can be cached by CDNs and browsers # max-age - Cache for 1 year (31536000 seconds) # immutable - Never revalidate, file won't change
Server Configuration Examples
Nginx
location ~* \.(woff2?|ttf|otf|eot)$ {
expires 1y;
add_header Cache-Control "public, immutable";
add_header Access-Control-Allow-Origin "*";
}Apache (.htaccess)
<FilesMatch "\.(woff2?|ttf|otf|eot)$">
Header set Cache-Control "public, max-age=31536000, immutable"
</FilesMatch>Vercel (vercel.json)
{
"headers": [
{
"source": "/fonts/(.*)",
"headers": [
{ "key": "Cache-Control", "value": "public, max-age=31536000, immutable" }
]
}
]
}Cache Busting with Versioned Filenames
When using long cache times, you need a way to force users to download updated fonts. Version the filename instead of using query strings.
/* Good: Version in filename */
@font-face {
font-family: 'CustomFont';
src: url('/fonts/custom-v2.woff2') format('woff2');
}
/* Bad: Query string (ignored by some CDNs) */
@font-face {
font-family: 'CustomFont';
src: url('/fonts/custom.woff2?v=2') format('woff2');
}
/* Also Good: Content hash */
@font-face {
font-family: 'CustomFont';
src: url('/fonts/custom.a1b2c3d4.woff2') format('woff2');
}CDN Caching
CDNs cache fonts at edge locations worldwide, reducing latency for global users. Most CDNs respect Cache-Control headers.
Cloudflare
Automatically caches based on Cache-Control. Enable "Cache Everything" page rule for fonts if needed.
# Cloudflare Page Rule URL: *example.com/fonts/* Cache Level: Cache Everything Edge Cache TTL: 1 month
AWS CloudFront
# CloudFront Cache Behavior Path Pattern: /fonts/* TTL Settings: Minimum: 86400 Maximum: 31536000 Default: 31536000
CORS Headers
When serving fonts from a CDN on a different domain, ensure Access-Control-Allow-Origin headers are set, or fonts will be blocked.
Service Worker Caching
Service workers provide the most reliable caching, enabling offline font access and instant loads.
// service-worker.js
const FONT_CACHE = 'fonts-v1';
const FONTS = [
'/fonts/main.woff2',
'/fonts/heading.woff2',
];
// Cache fonts on install
self.addEventListener('install', (event) => {
event.waitUntil(
caches.open(FONT_CACHE).then((cache) => cache.addAll(FONTS))
);
});
// Serve fonts from cache, fallback to network
self.addEventListener('fetch', (event) => {
if (event.request.url.includes('/fonts/')) {
event.respondWith(
caches.match(event.request).then((response) => {
return response || fetch(event.request).then((fetchResponse) => {
// Cache new fonts
const clone = fetchResponse.clone();
caches.open(FONT_CACHE).then((cache) => cache.put(event.request, clone));
return fetchResponse;
});
})
);
}
});Verifying Cache Behavior
Chrome DevTools
Network tab → Font request → Headers tab. Look for:
Cache-Control: public, max-age=31536000, immutable- Size column shows "(disk cache)" on repeat visits
- Time column shows 0ms for cached fonts
curl Command
curl -I https://example.com/fonts/main.woff2 # Look for: # Cache-Control: public, max-age=31536000, immutable # Access-Control-Allow-Origin: *
Additional Resources
Optimize Your Fonts
Smaller fonts cache faster and use less storage. Convert and subset your fonts.
Subset Fonts NowWritten & Verified by
Sarah Mitchell
Product Designer, Font Specialist
Font Caching FAQs
Common questions about browser caching and CDN strategies
