The Problem

When loading web fonts (WOFF2, WOFF, TTF) from a CDN or different domain, the browser enforces CORS. If the CDN does not include the proper Access-Control-Allow-Origin header, the font fails to load and the browser falls back to system fonts.

Symptoms

  • Custom fonts do not render, system fonts appear instead
  • Console: "Font from origin has been blocked by CORS policy"
  • Layout shift when fallback font loads first, then font fails
  • Fonts load in Chrome but not Firefox (Firefox is stricter)

Real Error Message

bash
Access to font at 'https://cdn.example.com/fonts/roboto.woff2'
from origin 'https://example.com' has been blocked by CORS policy:
No 'Access-Control-Allow-Origin' header is present on the
requested resource.

How to Fix It

Fix 1: Configure CDN CORS Headers

nginx
# On the CDN server (or origin server)
location ~* \.(woff2|woff|ttf|otf|eot)$ {
  add_header Access-Control-Allow-Origin "https://example.com";
  add_header Cache-Control "public, max-age=31536000";
}

For AWS CloudFront, add CORS headers in the distribution settings or use Lambda@Edge:

javascript
// Lambda@Edge viewer response
exports.handler = async (event) => {
  const response = event.Records[0].cf.response;
  response.headers['access-control-allow-origin'] = [
    { key: 'Access-Control-Allow-Origin', value: 'https://example.com' }
  ];
  return response;
};

Fix 2: Use Crossorigin Attribute

html
<link
  rel="preload"
  href="https://cdn.example.com/fonts/roboto.woff2"
  as="font"
  type="font/woff2"
  crossorigin="anonymous"
>

Fix 3: Use Google Fonts with CORS Support

html
<!-- Google Fonts handles CORS automatically -->
<link href="https://fonts.googleapis.com/css2?family=Roboto:wght@400;700&display=swap" rel="stylesheet">

Fix 4: Self-Host Fonts

css
@font-face {
  font-family: 'Roboto';
  src: url('/fonts/roboto.woff2') format('woff2'),
       url('/fonts/roboto.woff') format('woff');
  font-weight: 400;
  font-display: swap;
}

Self-hosting eliminates CORS issues entirely.

Fix 5: Verify CORS with curl

```bash curl -I https://cdn.example.com/fonts/roboto.woff2 \ -H "Origin: https://example.com"

# Look for: # Access-Control-Allow-Origin: https://example.com ```

Fix 6: Handle Font Loading Errors

```javascript const font = new FontFace('Roboto', 'url(/fonts/roboto.woff2) format("woff2")');

font.load().then(loadedFont => { document.fonts.add(loadedFont); document.documentElement.style.fontFamily = 'Roboto, sans-serif'; }).catch(err => { console.warn('Font failed to load:', err); // System fallback fonts will be used }); ```