Deploy a web font without the usual surprises

Conversion is step one. Correct CSS, honest licensing, caching and browser verification are what make the font reliable in production.

Last reviewed 2026-08-24 · editorial and testing policy

A successful TTF-to-WOFF2 conversion proves that the output is structurally loadable. It does not prove that your site is serving the right weight, that the browser may fetch it across origins, or that your license permits web embedding. Use this checklist after converting with TTF to WOFF2.

1. Choose the smallest format set you actually need

WOFF2 is the default for modern browsers. It applies Brotli compression plus font-specific transforms and is normally substantially smaller than the original TTF or OTF. WOFF 1.0 is a compatibility fallback for old browser fleets. If your supported browsers all understand WOFF2, shipping both formats adds another file to maintain without helping users.

Keep the original desktop font outside your public web directory. It remains the source for future weights or subsets; the web build should contain only the font files the page actually uses.

2. Check the license before the code

A desktop-font license and a web-font license are often different products. Local conversion does not create embedding rights. Confirm that the license permits web use, whether the font may be modified or subset, and whether traffic or domain limits apply. For open fonts, retain the license notice with your source materials even when the license does not require a visible credit.

3. Declare each real style and weight

@font-face {
  font-family: 'Brand Sans';
  src: url('/fonts/brand-sans-regular.woff2') format('woff2');
  font-style: normal;
  font-weight: 400;
  font-display: swap;
}

The declared weight must match the font file. Labeling a regular file as weights 400 through 700 does not create a bold font; it asks the browser to synthesize one. Add a separate declaration for every file you ship, or use the correct weight range for a verified variable font.

4. Put performance work in the right order

  • Subset only when you understand the character coverage. Removing Korean, accented Latin, symbols or currency glyphs can create silent fallback in the middle of a line.
  • Preload only a critical above-the-fold font. Preloading every weight competes with CSS, images and scripts and can make the page slower.
  • Use long immutable caching for versioned files. A content hash in the filename lets you cache for a year and still release a corrected font immediately.
  • Prefer same-origin hosting. It avoids a third-party dependency and makes CORS configuration simpler.
<link rel="preload"
      href="/fonts/brand-sans-regular.woff2"
      as="font" type="font/woff2" crossorigin>

The crossorigin attribute is required for a font preload even when the font is on the same origin, because font fetches use CORS mode. The preload URL must exactly match the URL in @font-face or the browser may download the file twice.

5. Verify the production response, not just the local preview

  1. Open DevTools → Network, filter by “font”, and reload with the cache disabled.
  2. Confirm one 200 response for each expected font and no 404, CORS or MIME errors.
  3. In the Elements or Computed panel, verify the rendered font name and weight on normal, bold and italic text.
  4. Test a character outside basic English — an accented name, currency symbol, or the scripts your audience uses — to detect accidental subsetting.
  5. Reload once with the cache enabled and confirm the response comes from memory or disk cache.

Common failures and the shortest diagnosis

SymptomLikely causeCheck
Font never appearsWrong URL or blocked responseNetwork status, console CORS error
Regular works, bold looks softBrowser synthesized boldActual file and declared font-weight
Some characters change typefaceGlyphs missing from the font/subsetCoverage with representative copy
Font downloads twicePreload URL/attributes differ from CSSExact URL, type and crossorigin
Text stays invisible during loadBlocking font-display behaviorUse font-display: swap or optional deliberately

Need an older-browser fallback? Convert the same source with TTF to WOFF and list WOFF2 first, WOFF second. Keep the source and both outputs private until you have confirmed the license.