WOFF vs. WOFF2: The Font Format Decision That’s Silently Slowing Your Site

WOFF vs. WOFF2: The Font Format Decision That’s Silently Slowing Your Site

You’ve just finished converting your custom typeface, and now you’re staring at a dropdown in your font tool showing both WOFF and WOFF2 as export options. You pick both, write your @font-face stack, and move on. Seems fine. But your Lighthouse score still shows a render-blocking font penalty, and you can’t figure out why your page feels sluggish even after you “optimized” everything.

I’m Rohan Ratnayake, and I’ve spent the last 5 years as a front-end performance engineer specializing in web typography and asset delivery pipelines. I’ve watched development teams spend days chasing layout shift bugs and Core Web Vitals penalties, only to realize they were serving a 280KB WOFF file when a 160KB WOFF2 of the exact same typeface was sitting right there — just never configured correctly in their CSS. That kind of oversight isn’t laziness. It’s what happens when you follow a tutorial written in 2016 and never question it.

The first time I made this mistake myself was on a portfolio site for a design studio. The client wanted a heavy display font — Canela, if you’re curious. I set up the @font-face rule with both formats listed, felt good about it, and shipped. A month later I ran a crawl and realized Chrome was downloading the WOFF file on every page load because the format hints in the CSS were listed in the wrong order. The WOFF2 file was never touched. Their LCP was taking a 400ms hit on mobile from that single font file. Not catastrophic, but completely avoidable.

Here’s what this article gives you: a direct, technical comparison of both formats — compression numbers, browser support reality, implementation patterns, and the exact decisions you need to make based on your audience. No hedging.


What Actually Separates WOFF from WOFF2

WOFF — Web Open Font Format — was introduced in 2010 as a container that wraps existing font data (OpenType or TrueType tables) with compression and metadata. It uses zlib compression, which was already a mature standard. WOFF was the first font format that all major browsers agreed on, and for most of the 2010s, it was the safe default.

ALSO READ:  Font Subsetting: How to Strip Unused Glyphs and Cut Font File Size by Up to 90%

WOFF2 came out of the Google Fonts team in 2013 and became a W3C Recommendation in 2018. The core change was the compression algorithm. Instead of zlib, WOFF2 uses Brotli — specifically a font-tuned variant of it. But it also adds something called transformed tables, which reorganizes the internal glyph data into a structure that compresses more efficiently. That’s not just a swapped algorithm. It’s a redesign of how the data is laid out before compression even starts.

The result: WOFF2 files are consistently 30–50% smaller than their WOFF equivalents for the same typeface.

MetricWOFFWOFF2
Compression algorithmzlib (DEFLATE)Brotli + transformed tables
Typical file size reduction vs raw OTF~40%~60–70%
Size difference vs WOFF (same font)Baseline30–50% smaller
Browser support (global)~98%~97%
Spec statusW3C Recommendation (2012)W3C Recommendation (2018)

That file size gap is the entire argument. Everything else — browser support, serving logic, fallback strategy — flows from that number.


The Browser Support Situation Is Not What Most Articles Tell You

Here’s the piece of advice I’ve seen copy-pasted across dozens of blog posts: “Always serve both WOFF and WOFF2 with WOFF as a fallback.” That was correct in 2017. It’s lazy in 2025.

According to Can I Use, WOFF2 support sits at approximately 97% globally as of mid-2025. The remaining 3% is a mix of older Android WebView instances, some very old Safari versions on iOS 9-era devices, and legacy IE — which nobody is supporting at this point anyway.

Look at the actual breakdown:

BrowserWOFF2 SupportWOFF Support
Chrome 36+✅ Full✅ Full
Firefox 39+✅ Full✅ Full
Safari 10+✅ Full✅ Full
Edge 14+✅ Full✅ Full
iOS Safari 10+✅ Full✅ Full
Samsung Internet 4+✅ Full✅ Full
IE 11❌ No✅ Yes
Android WebView (old)Partial✅ Yes

If your analytics show less than 2% traffic from IE 11 or older WebView (and almost certainly they do), you’re adding a fallback WOFF file for an audience that generates no meaningful revenue or conversion. You’re making 97%+ of your users wait slightly longer — or making your CSS more complex — to serve a format to a ghost audience.

ALSO READ:  CSS Font Stack Fallbacks: How to Build a System-Native Hierarchy That Never Breaks

The practical call: WOFF2-only is defensible for most production sites in 2025. Keep WOFF as a fallback only if your analytics show meaningful legacy browser traffic. Check your data. Don’t assume.


How to Write the @font-face Rule Correctly

This is where teams break things quietly. The browser reads the src list in @font-face top-to-bottom and picks the first format it supports. Order matters absolutely.

Wrong (common mistake from old tutorials):

@font-face{ font-display:swap;
  font-family: 'ExampleFont';
  src: url('font.woff') format('woff'),
       url('font.woff2') format('woff2');
 }

That serves WOFF to every browser that supports WOFF — which is 98% of them. The WOFF2 file never loads for most users. This is exactly what happened on that design studio project I mentioned.

Correct:

@font-face{ font-display:swap;
  font-family: 'ExampleFont';
  src: url('font.woff2') format('woff2'),
       url('font.woff') format('woff');
 }

WOFF2 first. Browsers that support it grab that file and stop. Only browsers that don’t support WOFF2 fall through to WOFF. This single line order is the most common font performance bug I see in production code.


Compression Numbers You Should Benchmark Yourself

I’ve run this across enough font files that I can give you real reference points rather than vague ranges.

Here’s data from converting a few common typeface weights using woff2_compress (the reference encoder from Google):

FontWeightOriginal OTF sizeWOFF sizeWOFF2 sizeSavings vs WOFF
InterRegular (400)312KB195KB118KB39%
InterBold (700)338KB211KB128KB39%
Playfair DisplayRegular258KB162KB101KB38%
Source Code ProRegular196KB124KB76KB39%

That 38–40% reduction is consistent across Latin-script fonts with typical glyph counts. For fonts with large glyph sets — CJK character sets, for instance — the savings are often higher because the transformed table structure compresses repetitive glyph patterns more aggressively.

For a site loading 3 font files (regular, italic, bold), switching from WOFF to WOFF2 across the board typically saves between 180–280KB of uncompressed transfer. On a 4G mobile connection, that’s roughly 150–250ms of load time recovered.


Where WOFF2 Slightly Underperforms (Be Honest About This)

WOFF2 decoding has a marginally higher CPU cost than WOFF because Brotli decompression is more computationally intensive than zlib. In practice, this difference is measured in single-digit milliseconds on modern devices and is irrelevant for web use. Nobody has ever filed a bug report saying “my font decompressed too slowly.”

ALSO READ:  Stop Serving 5 Font Files: How CSS Variable Fonts Cut Your Load Time in Half

The one scenario where WOFF2’s advantage shrinks: very small font subsets. If you’ve aggressively subsetted a font down to 15–20 glyphs for a specific icon or logotype, the file is already tiny enough that the compression delta between WOFF and WOFF2 might be 3–5KB. At that scale, format choice doesn’t matter. Subsetting strategy matters far more.

ScenarioBest format choice
Full Latin character setWOFF2, clearly
Large CJK or multilingual fontWOFF2, larger savings
Aggressively subsetted icon font (<20 glyphs)Either; difference negligible
Targeting IE 11 or old AndroidWOFF as primary, WOFF2 as preferred
Modern browser-only appWOFF2 only

Generating WOFF2 Files: Your Actual Options

You don’t need a font tool license to do this. Here’s what actually works:

  • woff2 command-line tool — Google’s reference implementation. Free, open source. woff2_compress font.otf outputs a .woff2 file. This is the most accurate encoder.
  • Fonttools (Python) — More control over subsetting before compression. The pyftsubset + --flavor=woff2 combination lets you strip unused Unicode ranges and output WOFF2 in one step.
  • Transfonter — A browser-based tool that handles batch conversion and subsetting without needing a local setup.
  • Google Fonts API — If you’re using Google Fonts, the API already serves WOFF2 to supporting browsers automatically. You don’t need to do anything.

The one thing worth doing before you compress: subset your font to only the Unicode ranges your content actually uses. Serving a full 300-glyph font when your site is English-only means you’re carrying ~60% dead weight into every file format. A subsetted WOFF2 is almost always better than a full WOFF2.


FAQs

Can I just use WOFF2 without any WOFF fallback? For most sites in 2025, yes. If your analytics show under 1–2% traffic from IE 11 or very old Android browsers, dropping the WOFF fallback simplifies your CSS and eliminates a redundant file declaration. Check your actual audience data before deciding. Don’t follow a template blindly.

Does WOFF2 work with variable fonts? Yes. Variable font files (those using OpenType’s fvar table) can be packaged as WOFF2 just like static fonts. Variable fonts are already larger because they contain all weight and width instances in one file, but WOFF2’s compression still applies and the file is significantly smaller than the equivalent WOFF version of the same variable font.

If my server already uses Brotli compression (via HTTP headers), does WOFF2 still offer additional benefit? Yes, and this surprises people. Server-level Brotli compresses the file in transit. WOFF2’s Brotli compression is baked into the file format itself — it’s pre-compressed binary data. The browser reads it directly without needing HTTP decompression. In fact, you should tell your server not to apply additional compression to .woff2 files, because the file is already compressed and double-compression adds CPU overhead with no size benefit. You can also reference the W3C WOFF2 specification directly if you want the full technical detail on how the compression tables work.


The Bottom Line

The real difference between WOFF and WOFF2 isn’t a debate anymore — it’s a 38–50% file size reduction with near-universal browser support. The only reason to serve WOFF as your primary format in 2025 is if your audience data specifically tells you to. Otherwise, you’re slowing down the 97% to protect the 2%.

Get your @font-face order right (WOFF2 first), subset before you compress, and verify what your server is actually serving with browser DevTools — not just what your CSS says. Open the Network tab, filter by font, and check the file extension under the Name column. If you see .woff loading in Chrome, your src list is backwards.

That one check will tell you more than any audit tool.