Close
or Register
Login
 

F Blog Home

The New Bulletproof @Font-Face Syntax

February 3, 2011

spacer

Updated: April 21, 2011 10:49 AM EST

Since the beginning of the 'webfont revolution' we've relied on somewhat hacky @font-face declarations to get webfonts loading cross-browser. Could there be a better way? One that's clear and compatible with future browsers?

Short history

In September 2009, Paul Irish came up with the Bulletproof syntax for writing the @font-face declaration. It was compact and worked across all browsers at the time. Recent, growing complaints that fonts weren't loading in Android, led me to recommended the Mo' Bulletproofer syntax devised by Richard Fink instead. Unfortunately Mo' Bulletproofer requires double declarations. Defining each font twice in the CSS is cumbersome, so I looked for a better solution.

The “Fontspring @Font-Face Syntax”

The code should have been clean, clear and simple all along. Finally, it is:

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

What? I don't get it.

The hack trick that makes this work is the '?' following the EOT filename. Seriously.

How it works

Internet Explorer <9 has a bug in the parser for the src attribute. If you include more than one font format in the src, IE fails to load it and reports a 404 error. The reason is that IE attempts to load as a file everything between the opening parenthesis all the way to the very last closing parenthesis. To deal with that wrong behavior, you merely declare the EOT first and append a single question mark. The question mark fools IE into thinking the rest of the string is a query string and loads just the EOT file. The other browsers follow the spec and select the format they need based on the src cascade and the format hint.

Browser compatibility

Safari 5.03, IE 6-9, Firefox 3.6-4, Chrome 8, iOS 3.2-4.2, Android 2.2-2.3, Opera 11

What about data uri fonts?

You can use this syntax as well to embed your fonts into a stylesheet. For it to work does require two declarations however. But if you are going this route, what is an extra declaration? Note that the format hint for the EOT needs to be 'embedded-opentype.'

@font-face {
	font-family: 'MyFontFamily';
	src: url('myfont-webfont.eot?') format('embedded-opentype');
	}
	
@font-face {
  font-family: 'MyFontFamily';
    url(data:font/truetype;charset=utf-8;base64,BASE64_ENCODED_DATA_HERE)  format('truetype'),
    url(data:font/woff;charset=utf-8;base64,BASE64_ENCODED_DATA_HERE)  format('woff'),
    url('myfont-webfont.svg#svgFontName') format('svg');
}

Albert Ward offered to translate this post to Bulgarian

Update 1 - Feb 3, 2011

The CSSNinja made a great observation about how to get IE9 to take a WOFF instead of the EOT. He suggested adding a hash to the format hint of the EOT. This works because IE9 doesn't recognize the format hint '#embedded-opentype.' So I modified the syntax to reflect his finding. I changed the format hint from 'embedded-opentype' to 'eot' which IE9 doesn't understand either and therefore moves on to the WOFF. We've reverted back to the correct format hint for eot, format('embedded-opentype') due to issues with serving on IIS. See this post for details.

Update 2 - Feb 4, 2011

IE was failing to load webfonts if the page was loaded locally. Turns out that IE prefers the '?' question mark character. The code has been updated to reflect this. Originally this post lauded the magical '#' hash. Hat tip to Chris Neale for the idea.

Update 3 - Feb 21, 2011

In response to this syntax not working in IE9 Compatibility modes (as well as an extended conversation with Microsoft) we've updated the syntax slightly. The revision adds redundancy, but further bulletproofs the method. Please see our separate post about this here.

Update 4 - April 21, 2011

When this syntax is used on an IIS server, IE9 users may not see the font. This can be solved in two ways. 1) Add the WOFF format to the list of MIME types. or 2) change the format('eot') portion to format('embedded-opentype'). Either one will solve issues with IE9.

143 Comments

spacer

Andrew Staffell

great work - will start testing straight away.

February 3, 2011 at 12:33 PM

spacer

Richard Fink

Ethan,

My hat is off to you for thinking of a hash mark!
Paul Irish reports that his recent testing of IE9 was done on Preview 7. Since an RC version of IE9 is expected in a few days, judgment is premature, I think, until we are all hands-on with that, at least.
As for the double-download in IE9 that Paul reported, that's easily fixed with the first declaration in Mo' Bulletproofer being within conditional comments - conditional comments which will probably be pre-existing on the web page, anyway - making it pretty convenient to cordon off the "less than" IE9 rules.

February 3, 2011 at 12:34 PM

spacer

Tom

Cool. :D The simplest solutions are the bestest.

February 3, 2011 at 12:34 PM

spacer

Erik Vorhes

I can confirm that this syntax also works in Internet Explorer 6 and Opera 11. Beautiful!

February 3, 2011 at 12:36 PM

spacer

Derek

Very clever!

February 3, 2011 at 12:41 PM

spacer

Paul Irish

Nailed it.

February 3, 2011 at 12:41 PM

spacer

Joen

I wouldn't say this new magical syntax is facepalm-simple, but it is remarkably elegant considering the wealth of stuff it distills.

Three thumbs up.

February 3, 2011 at 12:49 PM

spacer

Niki Brown

Shazam! Thanks for all the hard work you do! The web is a much nicer place now :)

February 3, 2011 at 01:03 PM

spacer

Christopher Beckwith

Bravo, updating my code as we speak...well...type.

February 3, 2011 at 01:11 PM

spacer

Spencer

Great work guys! Thanks so much for pushing the industry!

typo:
"Could there a better way?" = "Could there be a better way?"

February 3, 2011 at 01:25 PM

spacer

Peter Gasston

Nice one! How on earth did you think of that?

February 3, 2011 at 01:26 PM

spacer

Ethan Dunham

@Spencer - Thanks! And typo fixed.

@Peter - Trial and error and more error. Finally occurred to me after staring at the error logs output by IE.

February 3, 2011 at 01:31 PM

spacer

Jonathan Snook

Well done, Ethan! Absolutely fabulous!

February 3, 2011 at 01:45 PM

spacer

Stephanie (Sullivan) Rewis

Awesome work! I was just working on this yesterday. I shall implement your syntax right away! Thank you. :)

February 3, 2011 at 01:54 PM

spacer

Marius Ciobotaru

Great job.

February 3, 2011 at 01:57 PM

spacer

Raphael Essoo-Snowdon

Brilliant. Just brilliant!

February 3, 2011 at 02:03 PM

spacer

Jason Cranford Teague

Brilliant!

February 3, 2011 at 02:07 PM

spacer

Ethan Dunham

Thanks all. I am merely standing on the shoulders of others.

February 3, 2011 at 02:08 PM

spacer

Agos

Truly brilliant. And I wouldn't even call it a hack!

February 3, 2011 at 02:10 PM

spacer

Jean-Philippe Sirois

Great discovery!

I’ve Already updated my current project Font-Face CSS.

This should be part of Font Squirrel generator too.

Thanks!

February 3, 2011 at 02:15 PM

spacer

Richard Fink

I don't know about anyone else, but I'm hoping this is IT.
With some variation of the "no-404" double declaration hack relegated to special cases where LESS THAN IE9 CSS rules must be separated from the standard compliant rules because of the other ways in which IE6,7, and 8 differ.
In testing: test with the URL inside double quotes, single quotes, and with no quotes.
If the font displays, don't accept that as proof of anything - make sure you use Fiddler or some other app or method to make sure there is no 404 and that ONLY the font file you expect is downloading.
Looking forward to seeing how this tests out.
Nice.

February 3, 2011 at 02:18 PM

spacer

Denise Jacobs

Teaching this in my next CSS3 training. Nicely done! I've always disliked the double declaration -- too messy.

February 3, 2011 at 02:26 PM

spacer

Matt Wiebe

Well done Ethan. Lovely.

I made a test page to show that, at the very least, IE is using the EOT font and not the WOFF: somadesign.ca/demos/IE9-WOFF-Test/bulletproofest.html That won't say anything about double downloads for IE, but I'm guessing we'll be sure of that soon enough.

February 3, 2011 at 02:27 PM

spacer

NetRoY

simply brilliant .. thanks man :)

February 3, 2011 at 02:32 PM

spacer

Zoltan Hawryluk

Awesome with a capital AWE! :-) Going to test further, but looks <tony_the_tiger>G-r-r-r-r-EAT</tony_the_tiger> so far. Hats off to you!

February 3, 2011 at 02:35 PM

spacer

Ethan Dunham

It should be noted that IE9 will always download the EOT instead of the WOFF using this syntax. This shouldn't be much of an issue as we will soon be offering compressed EOTs as well.

February 3, 2011 at 02:38 PM

spacer

Leads

Sweet

February 3, 2011 at 02:40 PM

spacer

Thijs van der Vossen

Lovely! You don’t know how happy this makes me. :)

February 3, 2011 at 03:02 PM

spacer

Ryan Corradini

Brilliant. Excellent work.

February 3, 2011 at 03:03 PM

spacer

Wilkins

This is effing awesome. It's better than font-squirrel's latest implementation which isolates IE and other browsers loading into two sections. Well done!

February 3, 2011 at 03:19 PM

spacer

chapolito

yipee! great work Ethan, thanks for making life easier for the rest of us!

February 3, 2011 at 03:19 PM

spacer

Stephanie (Sullivan) Rewis

I've just tested a Galaxy Tab, HTC Desire HD, iPad and iPhone (since everyone else has tested browsers). I'm thrilled to now have my fonts properly appearing in my Android devices (and iOS is still fine).

February 3, 2011 at 03:30 PM

spacer

Erica J

Strikingly clever! Beautiful work, Ethan!

February 3, 2011 at 03:45 PM

spacer

Brian Klepper

Amazingly simple solution. Thanks for this 'Final' solution :)

February 3, 2011 at 03:58 PM

spacer

Batfan

Fantastic work my friend. Sure beats having 2 stylesheets and using conditional css. Thanks :)

February 3, 2011 at 04:04 PM

spacer

Andreas Papula

Thx for your work!
I'll use this in upcoming Projects (and update my existing Projects asap).

February 3, 2011 at 04:09 PM

spacer

karl

It is working with Opera 11.01. You can add it to your list.

February 3, 2011 at 04:11 PM

spacer

darcy

HMmm, I'm not sure what I did wrong. @font-face was working okay for me on most browsers, i changed it to this and broke Chrome, Safari and FF on Mac. Probably user error. I'll see what I can figure out.

I wonder if it's because I have it in a /fonts/ directory?

February 3, 2011 at 04:15 PM

spacer

admazy

omg! just in time :)

February 3, 2011 at 04:18 PM

spacer

Ethan Dunham

@darcy - No, not likely. Give us a URL to peek at...

February 3, 2011 at 04:24 PM

spacer

Kirk Franklin

Is the #webfontFqDaNIX6 necessary after the svg filename?

February 3, 2011 at 04:34 PM

spacer

darcy

Confirming it was indeed, operator error. ;)

February 3, 2011 at 04:34 PM

spacer

Ethan Dunham

@kirk - No and yes. It is confusing. An SVG file requires a hash '#' along with the name of the font inside the actual SVG file. Will update my example.

February 3, 2011 at 04:42 PM

spacer

Geoff

Anyone know whether there are plans for Firefox to allow fonts hosted away from the main domain? Our lovely fonts are wasted on FF users, since I've got them on Amazon S3 at the moment...

February 3, 2011 at 04:52 PM

spacer

Paul Irish

Geoff, this is totally doable. (Also IE9 has the same "feature" :)

https://developer.mozilla.org/En/HTTP_Access_Control describes the process.

In apache, the config for cross-domain font serving looks like this: https://github.com/paulirish/html5-boilerplate/blob/1733f/.htaccess#L57-69

You should be able to declare this header for your AWS-hosted assets.

February 3, 2011 at 05:17 PM

spacer

Chris

Wow. You are a life saver. THANK YOU!

February 3, 2011 at 05:20 PM

spacer

Kirk Franklin

Cool, thanks, that makes more sense.

February 3, 2011 at 05:58 PM

gipoco.com is neither affiliated with the authors of this page nor responsible for its contents. This is a safe-cache copy of the original web site.