Type something to search...
WOFF2 vs. WOFF vs. TTF: Which Font Format Should You Use?

WOFF2 vs. WOFF vs. TTF: Which Font Format Should You Use?

You inherit a WordPress theme and open its stylesheet. Every @font-face rule lists five sources: EOT with a ?#iefix hack, WOFF2, WOFF, TTF, and an SVG font with a #fontname fragment. The theme folder holds 40 font files for what is really four weights of one typeface. You wonder which of these the browser actually uses, whether removing any of them will break something, and whether the TTF you just received from a designer can go straight onto the site.

Font formats are confusing mostly because of history. This article explains what each format is, how they differ in compression and capabilities, which browsers need what in 2026, how to write a clean @font-face rule, and how to convert between formats from the command line.

The Font Formats at a Glance

FormatFull nameTypeCompressionUse in 2026
WOFF2Web Open Font Format 2.0Web wrapperBrotli plus font-specific transformsThe only format you need for the web
WOFFWeb Open Font Format 1.0Web wrapperzlib (gzip-style)Legacy fallback; rarely needed
TTFTrueType FontDesktop/system fontNoneSource files, desktop, apps
OTFOpenType FontDesktop/system fontNone (CFF outlines are compact)Source files, desktop, apps
EOTEmbedded OpenTypeMicrosoft legacy formatOptional MTXObsolete (Internet Explorer only)
SVG fontSVG FontXML-based glyph formatNoneObsolete (removed from browsers)

The short answer: serve WOFF2, and only WOFF2, on the web. The rest of this article explains why that is safe and where the other formats still matter.

TTF and OTF: The Source Formats

TrueType (TTF) was developed by Apple in the late 1980s and licensed to Microsoft. It stores glyph outlines as quadratic Bézier curves and includes a powerful hinting language for controlling how glyphs render on low-resolution screens.

OpenType (OTF) was developed by Microsoft and Adobe as a superset of TrueType. An OpenType font can contain either TrueType outlines (in a glyf table, often still with a .ttf extension) or CFF/CFF2 outlines based on PostScript, which use cubic Bézier curves (typically with a .otf extension). OpenType also defines the layout features you use on the web, like kerning, ligatures, small caps, and alternate figures.

In practice, ".ttf versus .otf" tells you the outline flavor, not a capability difference. Both support OpenType features, and both can be variable fonts.

TTF and OTF are uncompressed. They are the formats you install on a computer, bundle in an iOS or Android app, or receive from a foundry as source files. They can be used on the web, since browsers support them, but they waste bandwidth, often weighing two to three times as much as the equivalent WOFF2.

WOFF: The First Web Format

WOFF (Web Open Font Format), published as a W3C Recommendation in 2012, is not a new kind of font. It is a wrapper around TTF or OTF data that compresses each font table with zlib and adds optional metadata and a private data block for license information.

WOFF solved two problems at once: it made fonts smaller to download, and it gave foundries a format that could not be installed directly as a desktop font, which made them more comfortable licensing fonts for web use. Typical savings over raw TTF are around 40%.

WOFF2: The Current Standard

WOFF2, a W3C Recommendation since 2018, keeps the same wrapper idea but replaces zlib with Brotli compression and adds a preprocessing step that transforms the glyph and location tables into a form that compresses much better.

The result is substantial: Google's evaluation found WOFF2 files around 30% smaller than WOFF on average, with some fonts saving considerably more. Compared with raw TTF, savings of 50–70% are common.

Example: one weight of a Latin sans-serifApproximate size
TTF (uncompressed)300KB
WOFF140KB
WOFF295KB
WOFF2, subset to Latin35KB

The last row shows that format alone is not the whole story. Combining WOFF2 with font subsetting delivers the biggest wins.

Decompression is fast enough on modern devices that the smaller download always wins over the CPU cost.

Browser Support in 2026

WOFF2 is supported in every current browser: Chrome and Edge since 2014–2016, Firefox since version 39, and Safari since version 10 on macOS Sierra and later and on iOS 10 and later. Global support is above 97%, and the remaining few percent are mostly very old Android browsers and Internet Explorer, which Microsoft retired in 2022.

FormatChrome / EdgeFirefoxSafariInternet Explorer
WOFF2YesYesYesNo
WOFFYesYesYes9–11
TTF / OTFYesYesYesPartial (with flags)
EOTNoNoNo6–11
SVG fontNoNoRemovedNo

If an ancient browser cannot load WOFF2, it simply renders your fallback font stack, which is a perfectly acceptable degraded experience. That is why the extra WOFF, TTF, EOT, and SVG sources in old themes are dead weight.

Writing a Modern @font-face Rule

For a static font:

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

For a variable font, you can add the tech() function, which lets browsers skip a source they cannot use:

@font-face {
  font-family: "Brand Sans";
  src: url("/fonts/brand-sans-var.woff2") format("woff2") tech(variations);
  font-weight: 100 900;
  font-style: normal;
  font-display: swap;
}

Older code may use format("woff2-variations"). Browsers still accept it, but format("woff2") tech(variations) is the current syntax. If you are unsure, a plain format("woff2") works in every browser that supports variable fonts. Our guide to using variable fonts in CSS covers the rest of the setup.

Cleaning Up a Legacy Rule

That inherited theme rule looks like this:

/* Before: legacy "bulletproof" syntax */
@font-face {
  font-family: "Brand Sans";
  src: url("brand-sans.eot");
  src: url("brand-sans.eot?#iefix") format("embedded-opentype"),
    url("brand-sans.woff2") format("woff2"),
    url("brand-sans.woff") format("woff"),
    url("brand-sans.ttf") format("truetype"),
    url("brand-sans.svg#BrandSans") format("svg");
  font-weight: 400;
}

Modern browsers stop at the first source they support, so they already download only the WOFF2. Removing the others changes nothing for current visitors, but it shrinks your CSS, simplifies your build, and removes files from your repository:

/* After */
@font-face {
  font-family: "Brand Sans";
  src: url("brand-sans.woff2") format("woff2");
  font-weight: 400;
  font-display: swap;
}

Order matters in the src list. If an old rule lists TTF before WOFF2, browsers download the larger TTF. That is a common, silent performance bug.

When You Might Still Use WOFF or TTF

  • WOFF as a fallback only if your analytics show meaningful traffic from browsers without WOFF2, such as embedded devices, kiosks, or old smart TVs. List it after WOFF2.
  • TTF/OTF for non-browser targets: native iOS and Android apps, desktop installation, design tools like Figma (when uploading local fonts), PDF generation libraries, and image generation tools. For example, Next.js ImageResponse for Open Graph images uses Satori, which accepts TTF, OTF, and WOFF, but not WOFF2.
  • TTF/OTF as source files in your repository, from which you generate WOFF2 at build time. Keep the source; ship the WOFF2.
  • Email. Web font support in email clients is limited, and where it exists (Apple Mail, iOS Mail) WOFF and WOFF2 both work. Always rely on a strong fallback stack in email.

Converting Fonts to WOFF2

Google's woff2 Tool

Google's reference encoder provides woff2_compress and woff2_decompress:

# macOS
brew install woff2

# Debian/Ubuntu
sudo apt install woff2

# Convert: writes brand-sans-regular.woff2 next to the input
woff2_compress brand-sans-regular.ttf

# Convert back to TTF for inspection
woff2_decompress brand-sans-regular.woff2

fontTools

fontTools can convert, and it is the better choice when you also want to subset in the same step:

pip install fonttools brotli

# Straight conversion
fonttools ttLib.woff2 compress -o brand-sans-regular.woff2 brand-sans-regular.ttf

# Subset and convert together
pyftsubset brand-sans-regular.ttf --unicodes="U+0000-00FF,U+2000-206F,U+20AC,U+2122" \
  --layout-features="*" --flavor=woff2 --output-file=brand-sans-latin.woff2

Batch Conversion

for f in fonts/src/*.ttf; do
  pyftsubset "$f" --unicodes-file=latin.txt --layout-features="*" \
    --flavor=woff2 --output-file="fonts/dist/$(basename "${f%.ttf}").woff2"
done

Avoid online converters for commercial fonts. Uploading a licensed font to a third-party service may violate the license, and some services alter metadata. Converting locally keeps you in control.

Licensing and Formats

Many commercial licenses specify which formats you may use on the web. Some foundries provide WOFF and WOFF2 files under a web license and forbid serving the desktop TTF/OTF, because raw desktop files are easy to download and install. Converting a desktop-licensed TTF to WOFF2 does not turn it into a web license. Check the EULA, and see our guide on understanding font licensing for the common license types.

Serving Fonts Correctly

Use the registered MIME types and long cache lifetimes:

ExtensionMIME type
.woff2font/woff2
.wofffont/woff
.ttffont/ttf
.otffont/otf

Do not apply gzip or Brotli compression to WOFF2 or WOFF responses at the server level. They are already compressed, so the server wastes CPU for little or no gain. Raw TTF and OTF files do benefit from server compression if you must serve them. For the rest of the delivery setup, including caching and preloading, see our guide on self-hosting Google Fonts.

Font Formats FAQ

For almost every site in 2026, no. WOFF2 is supported by all current browsers and by more than 97% of users globally. Browsers that lack it will use your fallback font stack. Add WOFF only if your own analytics show significant traffic from very old browsers.

Yes, browsers support TTF, but it is uncompressed and often two to three times larger than WOFF2. Convert it to WOFF2 first, and check that your license permits web use of the font.

Both are OpenType-compatible desktop formats. TTF files use TrueType quadratic outlines, while OTF files usually use CFF cubic outlines from PostScript. Both support OpenType layout features and variable font technology, and both convert to WOFF2 for the web.

No. WOFF2 compression is lossless. When you decompress a WOFF2 file, you get font data that renders identically to the original, though the bytes may not be identical because of the table transforms.

No. EOT was only supported by Internet Explorer, which Microsoft retired in 2022, and SVG fonts were removed from browsers years ago. Remove both from your @font-face rules.

Use WOFF2. Variable fonts compress well in WOFF2, and every browser that supports variable fonts also supports WOFF2. Declare the weight range in the @font-face rule and optionally add tech variations to the format.

Not WOFF or WOFF2, since they are already compressed and further compression adds CPU cost with no benefit. Uncompressed TTF and OTF files do shrink with gzip or Brotli if you have to serve them.

Conclusion

Font formats look complicated because a decade of browser history is still visible in old stylesheets. Today the decision is simple. TTF and OTF are source and desktop formats. WOFF was the first web wrapper and is now a legacy fallback. EOT and SVG fonts are obsolete. WOFF2, with Brotli compression and font-specific transforms, is smaller than everything else and supported everywhere that matters.

Ship WOFF2 only, keep TTF or OTF as source files in your repository, convert locally with woff2_compress or fontTools (subsetting in the same step), and clean legacy multi-format src lists out of old themes. Use TTF only where a non-browser tool demands it, and always check that your license covers the format you serve.

Here are some useful references for going deeper on font formats:

  1. W3C: WOFF File Format 2.0 — the WOFF2 specification, including Brotli compression and table transforms.
  2. MDN Web Docs: The Web Open Font Format (WOFF) — background on WOFF and WOFF2 and browser support.
  3. MDN Web Docs: @font-face src — the format() and tech() syntax for font sources.
  4. Microsoft Typography: OpenType specification — how TrueType and CFF outlines fit inside OpenType.
  5. GitHub: google/woff2 — the reference WOFF2 encoder and decoder with woff2_compress.
Share :

Related Posts

Ascenders, Descenders, and Baselines: The Anatomy of a Letterform

Ascenders, Descenders, and Baselines: The Anatomy of a Letterform

You align an icon next to a button label and it looks a pixel or two too high, no matter how you adjust vertical-align. You set overflow: hidden

Continue Reading
Are Google Fonts GDPR-Compliant?

Are Google Fonts GDPR-Compliant?

In late 2022, thousands of small business owners in Germany and Austria opened letters demanding a few hundred euros in "damages" because their websi

Continue Reading
How to Audit Web Font Performance with Lighthouse?

How to Audit Web Font Performance with Lighthouse?

A client sends you a screenshot of their PageSpeed Insights report: performance score 61, LCP 3.9 seconds, and a vague list of warnings. They want to

Continue Reading