When you’ve been in the web development game long enough, you see patterns repeat themselves. It wasn’t all that long ago that developers attempted the Sisyphean task of making all experiences identical for every user independent of their web browser or device’s technical capability. We’ve since learned to shed those shackles in pursuit of something far better: reach.

But even after this shift occurred, we carried the baggage of our old ways forward with web fonts. We described our @font-face syntax with one of the heaviest-duty adjectives available: Bulletproof. This word almost became synonymous with @font-face syntax. You see it everywhere:

The web font world has changed. It’s time to move the chains forward. Given that web fonts for readable content fall back to system fonts when formats are not supported, it’s ok to be progressive here. Here’s the modern @font-face syntax I’d recommend:

@font-face {
  font-family: Open Sans;
  src: url(opensans.woff2) format('woff2'),
       url(opensans.woff) format('woff');
}

Pretty simple, right? Just two formats. Much simpler than what we were using before:

@font-face {
  font-family: Open Sans;
  src: url('opensans.eot');
  src: url('opensans.eot?#iefix') format('embedded-opentype'),
       url('opensans.woff') format('woff'),
       url('opensans.ttf')  format('truetype'),
       url('opensans.svg#svgFontName') format('svg');
}

We’ve eliminated the Embedded OpenType (EOT) format (supported only by Internet Explorer and is the format served to IE versions up to 11) which required a strange double src declaration to workaround a syntax bug. Bram Stein, renowned web font performance expert, notes that while EOT formats can be compressed they are often served uncompressed, which is less than optimal given that newer WOFF files include compression by default.

We’ve eliminated the standalone TrueType/OpenType format because most web browsers support both WOFF and [True|Open]Type. It’s also worth noting that WOFF is just a container format—it adds a wrapper around existing TrueType/OpenType files.

Most importantly, we’ve eliminated the SVG font format. This archaic format is no longer necessary and using it over better formats like WOFF can be harmful. In fact, Chrome took the unusual step of removing SVG font format support from their web browser (with the exception of older Windows versions). How often do things get removed from the web platform? Rarely! You can read more about the history of issues with SVG fonts at @scottjehl’s Device Bugs repository.

So, that leaves us with only two font formats: WOFF2 and WOFF. The ordering here is very important: WOFF2 and then WOFF.

To summarize, here is a list of browsers we’ve relegated to use system fonts with this reduced format syntax:

  • IE 8
  • Firefox 3.5
  • Chrome 4
  • Safari 3 through 5
  • Opera 10.1
  • Mobile Safari (iOS) 3.2 through 4.3
  • Android 2.2 through 4.3

Android is perhaps the most contentious on this list: as of writing these operating system versions make up about 16.4% of Android usage. This does not count users of these operating systems that have installed Chrome on their devices manually—we’re specifically talking about users of the Android Browser here.

But don’t cry for these users—content will still be readable.

Simplified syntax is better for code health, cognitive load, and general software maintenance. Decreasing the number of formats also decreases the possibility that developers will list their font formats in the src attribute out of order. Remember that browsers use the first format they find that works—so if you don’t order them correctly the browser could waste resources (or render poorly) with a less-than optimal format.

Decreasing the number of font formats also simplifies the self-hosting your web fonts. Self hosting can allow more advanced and fine-grained control over how your web fonts are loaded to achieve maximum rendering performance[1]. I’ve written a slew of web font loading articles that showcase advanced font loading techniques, and the more advanced two-stage loading methods are easier to implement when self hosting.

[1] Act now and buy two bottles of web font loading drink powder mix to achieve maximum rendering performance and the third bottle is free.

Addendum: Okay, but what about icon fonts?

I did contribute to the Bulletproof @font-face phenomenon. However, a closer read of the icon font article I wrote reveals no discussion of @font-face syntax. Said differently: a bulletproof @font-face syntax won’t save your icon fonts. Just because the font format can be read and interpreted by an older web browser doesn’t mean that it won’t have loading issues, FOUT fallback inconsistencies, or that glyphs will be misread by screen readers. Unlike content fonts, icon fonts do not use progressive enhancement by default. They need additional care: to be paired with a font loading strategy and with default screen-reader-accessible fallback text. I’d recommend that you read the article to learn more about the myriad of issues with icon fonts.

Or, you could look toward the future and use SVG icons instead.

Addendum: Thank You

A big thank you to Bram Stein for reviewing and providing feedback on this post before publication.

ABOUT THE AUTHOR

Zach (@zachleat) is a Front End Engineer / Web Developer with Filament Group. He has given talks at Smashing Conference, O'Reilly Velocity, CSSConf, and The White House. He also herds NebraskaJS (a JavaScript meetup) and its eponymously named NebraskaJS Conference.

8 Responses to “No @font-face Syntax will ever be Bulletproof, Nor Should It Be”

  1. Chris

    re Icon fonts: If you are a bit careful what icons use which font codepoints some may work without the icon. I normally choose M or E for a Mail icon, x or the multiple for close or cancel icons, ^v for arrows and some icons which hopefully are in most system fonts. Not great but helps a bit I guess

  2. Matt

    >Simplified syntax is better for code health, cognitive load, and general software maintenance. Decreasing the number of formats also decreases the possibility that developers will list their font formats in the src attribute out of order.

    The difference between your examples is literally three lines of code. Is maintaining the proper order of three lines of code really too great a “cognitive load” to warrant preserving a core element of the browsing experience for 16% of Android users?

  3. Zach Leatherman

    I stand by my recommendation!

    Don’t forget that the font files themselves require maintenance (especially when subsetting requirements in a project’s lifecycle may change).

    Your project’s needs may be different and you are free to make your own choices. Feel free to re-add the TTF format in your own code if you’d like.

  4. Marc Cornellà

    It may be worth adding caniuse.com references to the support of WOFF vs TTF/OTF among browsers. Turns out WOFF is even better supported than TTF/OTF

  5. Tim Vereecke

    Hi Zach, Matt,

    Android Browser market share for versions 4.3 and lower is 0.73%* (based on caniuse.com) (* can differ from your demographics)

    So it boils down to a personal choice (when taking action today)

    – If 0.73% on mobile is acceptable and you prefer max simplicity go for the 2 line approach (woff2, woff in this order)
    – If 0.73% on mobile is not (yet) acceptable and you want simplicity go to 3 line approach (woff2, woff, ttf in this order)

    Revisit your approach when your next font maintenance is due. (as the % might have changed by then)

    Is that a nice summary of your 2 comments?
    Kind regards,
    Tim

  6. How to load web fonts asynchronously • NGOCLB

    […] descriptor. That’s all you need for modern browsers. You can read more about why the so-called “bulletproof @font-face” syntax is deprecated by Zach […]

  7. Robert Dundon

    Thanks for noting that “. . .WOFF is just a container format—it adds a wrapper around existing TrueType/OpenType files.”

    The more I know!

  8. Joe Fletcher

    Glad to see we can start promoting woff-only. On my last website, I used just woff2 & woff and wondered why all the code examples I came across were still using outdated eot/ttf/svg examples when woff covered all modern browsers.