How to woff vs woff2: when to ship both, when to pick one
- Step 1Segment your analytics by browser — In GA4 or Plausible, break sessions down by browser and version. If IE11 is under 0.1% and you have no embedded-WebKit audience, you can drop WOFF entirely — the saved request and bytes outweigh the lost legacy support.
- Step 2Decide: one format or two — WOFF2-only for consumer sites with modern audiences. WOFF2 + WOFF for B2B/enterprise/government where IE11 still shows up in the logs. Almost never add TTF — no browser that lacks WOFF support is in active, secured use.
- Step 3Generate the formats you chose — Run your source TTF/OTF through [TTF to WOFF2](/font-tools/ttf-to-woff2) for the primary, and [TTF to WOFF](/font-tools/ttf-to-woff) for the fallback. Convert from the original font, not from one web format to another, so each gets the best compression.
- Step 4Order the src list WOFF2-first — Put `url(...) format("woff2")` first, then `format("woff")`. Browsers walk the list in order and stop at the first format they support, so WOFF2-capable engines never download the larger WOFF. Wrong order means modern browsers fetch the bigger file.
- Step 5Always include format() hints — Without `format()`, a browser tries each `src` in turn — downloading and parsing each until one renders, wasting bandwidth. With hints it skips formats it can't use without fetching them. Use `woff2`, `woff`, `truetype`, `opentype` exactly.
- Step 6Verify the fallback in a real legacy engine — If IE11 support is the whole reason you shipped WOFF, prove it works in BrowserStack or a Windows VM with IE11. Watch for the gotcha that IE11 ignores `font-display` (it always uses block behaviour with a ~3s timeout).
Browser-support floor by format
The oldest engine that can render each format. WOFF2 covers everything modern; WOFF reaches one generation further back.
| Format | First supported | Notable exclusions | Practical coverage (2026) |
|---|---|---|---|
| WOFF2 | Chrome 36, Firefox 39, Safari 10, Edge 14 (2014-2016) | IE11, Edge Legacy ≤18, some old embedded WebKit | ~99%+ of real traffic |
| WOFF 1.0 | IE9, Chrome 5, Firefox 3.6, Safari 5.1 (2010-2011) | IE6-8 (needs EOT), ancient stock Android | ~99.9% — the legacy floor for the web |
TTF/OTF in @font-face | Older still, but no engine lacking WOFF is in secure use | — | Adds nothing over WOFF in practice |
| SVG Fonts | Old WebKit only | Dropped from every modern browser by ~2018 | Effectively dead — don't ship |
| EOT | IE6-IE11 only | Everything else | Only for IE6-8, which are <0.01% and unpatched |
Size and compression: WOFF vs WOFF2 vs source
Same sfnt font, three wrappers. Exact ratios vary with glyph count and outline complexity — measure your own fonts.
| Property | TTF/OTF (sfnt) | WOFF 1.0 | WOFF 2.0 |
|---|---|---|---|
| Compression | None | zlib/DEFLATE per table | Brotli over the whole font |
| Table transform | — | No | Yes (glyf/loca) |
| Magic bytes | 0x00010000 / OTTO | wOFF | wOF2 |
| Typical web size | Largest (100%) | ~55-65% of TTF | ~50% of TTF (~20-40% smaller than WOFF) |
| Largest gains on | — | Moderate, uniform | CJK / high-glyph-count fonts |
Which formats to ship by audience
A practical decision matrix. "Both" always means WOFF2 first, WOFF second.
| Audience | Recommended formats | Why |
|---|---|---|
| Consumer web, modern devices | WOFF2 only | IE11 traffic is negligible; one request, smallest bytes |
| B2B SaaS targeting Fortune 500 procurement | WOFF2 + WOFF | Locked corporate machines still run IE11 (3-5% seen) |
| Banking / insurance / government portals | WOFF2 + WOFF | IE11 concentrated 5-10% in these verticals |
| HTML email | Neither (system stack) | Outlook strips @font-face entirely; design the fallback |
| Internal tool, known modern browser | WOFF2 only | You control the client — no fallback needed |
Cookbook
Copy-pasteable @font-face blocks for each decision, plus how to confirm which format a browser actually fetched.
WOFF2-only — the 2026 default
ExampleFor modern consumer audiences this is correct and complete. One request, smallest file, no cargo-culted fallbacks.
@font-face {
font-family: "Inter";
font-weight: 400;
font-display: swap;
src: url("/fonts/inter.woff2") format("woff2");
}WOFF2 + WOFF — the IE11-safe pattern
ExampleWOFF2 first means Chrome/Firefox/Safari/Edge stop at the smaller file. IE11 skips the WOFF2 it can't parse and downloads the WOFF. No TTF — nothing needs it.
@font-face {
font-family: "Inter";
font-weight: 400;
font-display: swap;
src: url("/fonts/inter.woff2") format("woff2"),
url("/fonts/inter.woff") format("woff");
}The wrong order — and why it costs bytes
ExampleList WOFF first and modern browsers stop there, downloading the larger zlib file and never reaching the WOFF2. This is the single most common ordering mistake.
/* WRONG: WOFF first */
src: url("/fonts/inter.woff") format("woff"), /* Chrome stops HERE */
url("/fonts/inter.woff2") format("woff2"); /* never fetched */
/* RIGHT: WOFF2 first */
src: url("/fonts/inter.woff2") format("woff2"), /* Chrome stops HERE */
url("/fonts/inter.woff") format("woff");Confirm which file the browser actually loaded
ExampleOpen DevTools → Network → filter 'font'. You should see exactly one font request per @font-face. If you see both woff2 and woff fetched, your format() hints are missing or the order is wrong.
DevTools → Network → Fonts inter.woff2 200 34.1 KB ← modern browser: only this (inter.woff not requested) IE11 (BrowserStack): inter.woff 200 48.7 KB ← legacy: only this (inter.woff2 skipped via format hint)
Generate both from one source font
ExampleRun the original TTF/OTF through each converter — don't transcode WOFF2 to WOFF, which inflates. Then wire both into the src list.
Source: Inter-Regular.ttf (309 KB) → /font-tools/ttf-to-woff2 → inter.woff2 (~34 KB) → /font-tools/ttf-to-woff → inter.woff (~49 KB) Then paste both URLs into /font-tools/font-face-generator (check WOFF2 + WOFF) for an ordered, hinted block.
Edge cases and what actually happens
Every row below was probed against the live API. Some documented requirements (alphabetical axis order, numerical tuple order) are not actually enforced in practice — useful to know if you've been blaming the wrong thing for a 400.
You list WOFF before WOFF2
Wastes bandwidthBrowsers evaluate src entries in order and stop at the first format they support. If WOFF comes first, every modern browser downloads the larger zlib file and never reaches the smaller WOFF2 — the opposite of what you intended. Always order WOFF2 first. The @font-face Generator emits the correct order automatically.
You omit the format() hints
Wastes bandwidthWithout format(), the browser can't know which entries it supports without fetching them. It downloads and tries each src in order until one renders — so a modern browser may pull the WOFF before discovering it prefers the WOFF2. Always include format("woff2"), format("woff"), etc.
You serve WOFF2 to IE11 with no fallback
Fallback font shownIE11 cannot decode WOFF2 and silently ignores that src entry. With no WOFF (or other supported) fallback in the list, the element renders in the next font in the CSS stack. If IE11 matters, add a WOFF second; if it doesn't, this is the acceptable outcome of a WOFF2-only deployment.
You transcode WOFF2 to WOFF for the fallback
InefficientConverting an existing WOFF2 back to WOFF inflates it (Brotli unwrapped, recompressed with weaker zlib), so the fallback is larger than it should be. Generate the WOFF from the original TTF/OTF instead — same lossless tables, better compression. See the size note in the TTF to WOFF guide.
font-display is ignored in IE11
By designIE11 doesn't implement font-display — it always uses block behaviour (invisible text until the font loads, with a ~3s timeout). Set font-display: swap anyway: IE11 ignores it, but every modern browser honours it. The Font Display Strategy tool helps you pick the right value for the modern majority.
Adding TTF as a third src
Cargo cultA TTF entry in @font-face almost never helps — any browser missing WOFF support is unpatched and out of secure use. It just adds a large file to your asset budget and a third line to maintain. Drop it. For a true desktop fallback, ship a system font stack instead of a downloadable TTF.
Old Android stock browser in your tail
NegligibleThe Android stock browser is essentially dead — Chrome on Android dominates and supports WOFF2, and Samsung Internet does too. Pre-2015 stock browsers are a vanishing slice of traffic. Don't size your format strategy around them; a WOFF fallback covers the rare case for free.
Variable font with a WOFF fallback
Partial in legacyA variable font wraps fine to both WOFF2 and WOFF, but the engines that need the WOFF (IE11) never supported variable fonts — they render the default instance only. Modern engines use the WOFF2 with full axis support. This is a graceful degradation, not a packaging problem.
Frequently asked questions
Will Safari pick the right format?
Yes. Every modern browser checks the format() hint and skips entries it doesn't understand, choosing the first supported one in the list. Safari 10+ supports WOFF2, so with WOFF2 first it stops there and never fetches the WOFF fallback.
What happens if I omit format() hints?
The browser tries each src in order — downloading and parsing each one until it finds one it can render. That wastes bandwidth, because it may fetch a WOFF before realising it prefers a WOFF2 later in the list. Always include hints: woff2, woff, truetype, opentype.
Which browsers need WOFF but not WOFF2?
Essentially just IE11 (still ~0.1% globally, higher in some verticals), plus Edge Legacy (deprecated 2021) and a few embedded WebKit views without Brotli. For consumer audiences, WOFF2-only is correct. For IE11-locked enterprise, add WOFF as a second src.
How much smaller is WOFF2 than WOFF?
Typically 20-40% smaller. WOFF2 uses Brotli (a stronger algorithm than WOFF's zlib) plus a glyf/loca transform that reorganises outlines for better compression. The gap is widest on CJK and other high-glyph-count fonts. The underlying sfnt tables are identical in both.
Should I ship WOFF for older Android browsers?
No need. Chrome on Android has ~99% share and supports WOFF2, as does Samsung Internet. The pre-2015 stock-browser tail is negligible. If you've already shipped a WOFF fallback for IE11, it covers that tail for free — but don't add WOFF solely for Android.
Is WOFF2 a different font format from WOFF?
No — both are compression wrappers around the same sfnt container. WOFF 1.0 deflates each table with zlib; WOFF2 Brotli-compresses the whole font and adds a transform. The browser unwraps either one back to the same in-memory sfnt. The byte-level details are in the WOFF spec internals guide.
Do I still need TTF in my src list?
Almost never. No browser that lacks WOFF support is in active, patched use, so a TTF entry just adds a large file you'll never serve. Drop it. If you want a true non-download fallback, use a system font stack.
How do I generate WOFF and WOFF2 from the same font?
Run the original TTF/OTF through TTF to WOFF2 and TTF to WOFF separately — both convert from the source for best compression. Then assemble the src with the @font-face Generator, which orders WOFF2 first.
Does font-display affect the format decision?
Not directly, but it interacts with legacy support: IE11 ignores font-display and always blocks rendering until the font loads, while modern browsers honour your chosen value. Set swap (or your preferred value via the Font Display Strategy) for the modern majority; IE11 will simply ignore it.
How do I check which format a browser actually downloaded?
Open DevTools → Network → filter by font. You should see exactly one font request per @font-face. If both WOFF2 and WOFF are fetched, your hints are missing or your order is wrong. In a legacy engine like IE11 (via BrowserStack), confirm only the WOFF is fetched.
Is shipping both formats more work to maintain?
A little — two files per weight, two src lines. The cost is real but small if you automate generation. Script the conversions (see the batch WOFF guide) so a new weight produces both formats with one command, and a CI guard keeps them in sync.
What about EOT or SVG fonts for very old browsers?
Skip both. SVG Fonts were dropped from every modern browser by ~2018; EOT only ever helped IE6-8, which are below 0.01% and unpatched. WOFF is the practical legacy floor. Don't spend payload bytes on formats no secured browser uses.
Privacy first
Every JAD Font tool runs entirely in your browser using opentype.js and the wawoff2 WASM Brotli encoder. Your fonts never leave your device — verified by zero outbound network requests during processing.