How to Embed Webfonts Properly and How to Solve the Ambiguous "CSS3111: @font-face encountered unknown error"

@font-face error

In the present article, we will be discussing how to embed webfonts properly with good cross-browser support, focusing especially on Internet Explorer, which is known to be one of the most troublesome browsers when it comes to @font-face declarations. We will also clarify the meaning of the ambiguous CSS3111 error caused by certain webfonts in IE. Let's start, shall we?

Getting a @font-face declaration to work properly in every browser can sometimes be a really challenging task for a web developer, especially when it comes to older versions of Internet Explorer. Although IE9 offers a relatively good font embedding support, browser statistics show that even in the beginning in 2012 a little over 10% of the web users still use IE8 (which is actually more than the people currently using IE9) and almost 3% use IE7. There are even people still on IE6! These may sound like small numbers, but when you sum them up, you'll realize almost 15% of your users are using old versions of Internet Explorer and if you're the owner of a high traffic website with, say, 5 million unique visitors per month, that's 750,000 people!! Imagine the profits you may be missing, just because of a faulty embedded font ruining the look of your website in their old browsers. It's just terrible!

But why am I even talking about this? Well, because I have experienced and solved such issues myself for a number of times and sometimes the solutions were less than obvious. At the same time, a huge part of the information on the Internet that discusses this topic is either a bit obsolete, or a bit too scarce. But before we focus on the errors, I'd like to talk about how to properly embed fonts in a way that works well in all browsers.

Well, first of all, it is absolutely necessary that you have EOT, SVG, TTF & WOFF versions of your web font. Yes, nowadays all major browsers support TTF & WOFF font files, but everything older than Internet Explorer 9 requires EOT and some older versions of Mobile Safari & Opera Mobile require SVG, so as a general rule of thumb it's good to have them all prepared, just to be 100% sure that the number of users not being able to see your fancy custom font is reduced to minimum. (Check this page for a more detailed @font-face browser support list)

As for the actual CSS code used to embed fonts, there are about 3 popular code snippets that you can see reoccuring in most articles & tutorials on the Internet. The one that works best for me is this one:

    src: local('O'),
            url('') format('woff'),
            url('') format('truetype'),
            url('') format('svg');

...and I've used it in a good number of projects, but in fact I always minify that, so in my stylesheets it's usually all in one row, like this:

@font-face{font-family:'somefont';src:url('');src: local('O'),url('') format('woff'),url('') format('truetype'),url('') format('svg');font-weight:normal;font-style:normal;}

While some articles say that IE may fail loading your fonts if you minify your @font-face declaration, I can assure you this is a myth and nothing bad will happen. So don't hesitate to minify your stylesheets - it's absolutely OK to do it and it won't choke the CSS processor.

Another common myth claims that if your fonts are located on a remote server (a CDN for example) they won't render properly in all browsers. That's only partially true. Yes, without an explicit "Access-Control-Allow-Origin" header, Firefox and Internet Explorer won't display your webfonts (if you hit F12 to open up Developer Tools in IE and go to the Console tab, you will get the CSS3117: @font-face failed cross-origin request. Resource access is restricted. error) That's simply because IE and Firefox don't allow cross-domain fonts by default. On the other hand Google Chrome will load the fonts without a problem and if you're not aware of the cross-origin issue, debugging this may get really frustrating. While I personally prefer to place my fonts on the same domain too, you can still place them on a remote location and have them load successfuly in all browsers, as long as you add this declaration to your main .htaccess file:

<FilesMatch "\.(ttf|otf|eot|woff)$">  
    <IfModule mod_headers.c>
        Header set Access-Control-Allow-Origin"

This will add an "Access-Control-Allow-Origin" header to all of your font files, overriding the default setting for IE & Firefox.

Since we've already mentioned IE's F12 Developer Tools and discussed the CSS3117 error, it's worth pointing out that Developer Tools may actually be a really useful tool for debugging @font-face issues. All @font-face errors are reported in the Console tab of Developer Tools. You can check this list of CSS Error Codes and go through the error codes listed there to get a better idea of what you may expect.

CSS3117 is one of the common errors. Another common one is: CSS3114: @font-face failed OpenType embedding permission check. Permission must be Installable. CSS3114 usually occurs when the source of your EOT file was a locked TTF file (assuming you used a font face generator or did some type of TTF to EOT conversion). CSS3114 is almost always accompanied by the "mythical" CSS3111 error, but solving CSS3114 automatically fixes both, as CSS3111 in that case is provoked by CSS3114.

What is a locked TTF file? Well, all TTF files have an "embeddable" flag stored in them. This flag determines whether the font can be embedded in a file or on a website, or whether such actions are prohibited. There is a great free tool that allows you to alter that flag. It's called TTFPATCH. However, you have to understand that using TTFPATCH doesn't make embedding the font legal - you can easily "cheat" and make any non-embeddable font load in every browser, but this may be a copyright violation and the copyright holders may decide to sue you, so it's probably a better idea to just stick to fonts that are legally embeddable.

And now to our main highlight - the "CSS3111: @font-face encountered unknown error". This error is very ambiguous. If you have a look at MSDN again, you'll see its description says: "An unknown problem was encountered with the "Web Open Font Format (WOFF)", and "Embedded OpenType font (EOT)" of the Cascading Style Sheets (CSS) font". "Unknown Problem" doesn't sound too good to me - how am I supposed to solve an unknown problem? Fortunately we're given a hint here. It says: "Check source of the fonts". Indeed, CSS3111 is usually caused by an issue with the font's binary source. One of the popular online TTF to EOT converters for example produces EOT files with a NAME table that doesn't comply to the Microsoft standards, which results in EOT fonts that never load in IE and produce the CSS3111 error. So, when you experience a CSS3111, it is always good to try using a different TTF to EOT converter or font face generator.

Here's a list of my personal favorites:

Further reading:

As a conclusion, @font-face errors are sometimes hard to diagnose. I've been using a tool for a while called IETester. I liked IETester, because it allowed me to view IE8, IE7, IE6 and even IE5.5 versions of my websites on my shiny new Windows 7 machine. I got used to it so much that I started relying entirely on it for my projects. A few of them used webfonts. Everything seemed fine, because both the IE7 and IE8 tests displayed satisfying results - my @font-face declarations were being processed properly, but after a couple of months I received a complaint - the websites were "broken" in IE8. "It can't be true" I said and opened up IETester to only see that I'm right. But after a while, I decided to turn on one of my old machines, that still had IE8 on it and what did I see - no custom fonts, instead - an ugly system font that made the text way larger than what it was supposed to be, which on the other hand was breaking the layout and the site was looking really bad.

Now, don't get me wrong, IETester is still a great tool, but my point is - when debugging always rely on multiple sources. Nowadays, along with IETester, I use screenshot services like NetRenderer and BrowserShots to make sure that what IETester is displaying is 100% accurate.

Marin Bezhanov

Marin Bezhanov

Read more posts by this author.


You may also like

    Comments powered by Disqus