Serving Fonts from CDN
For maximum performance, we all know we must put our assets on CDN (another domain). Along with those assets are custom web fonts. Unfortunately custom web fonts via CDN (or any cross-domain font request) don't work in Firefox or Internet Explorer (correctly so, by spec) though they do work (incorrectly so) in Webkit-based browsers. They actually require custom CORS configurations to display properly. Here's the code you'll need to make that happen.
The .htaccess
or httpd.conf
Code
The code can be placed with the .htaccess
file or httpd.conf
file:
# Apache config <FilesMatch ".(eot|ttf|otf|woff)"> Header set Access-Control-Allow-Origin "*" </FilesMatch> # nginx config if ($filename ~* ^.*?\.(eot)|(ttf)|(woff)$){ add_header Access-Control-Allow-Origin *; }
This sets the Access-Control-Allow-Origin CORS configuration to allow pulling from all domains. List specific domains by comma if you want to serve fonts up to only specific domains. You'll want to serve up all font types appropriately in the case that the browser prefers one type.
To ensure the header is set properly, you can check using the curl utility:
$ curl -I https://some.cdn.otherdomain.net/media/fonts/somefont.ttf # Result HTTP/1.1 200 OK Server: Apache X-Backend-Server: developer1.webapp.scl3.mozilla.com Content-Type: text/plain; charset=UTF-8 Access-Control-Allow-Origin: * ETag: "4dece1737ba40" Last-Modified: Mon, 10 Jun 2013 15:04:01 GMT X-Cache-Info: caching Cache-Control: max-age=604795 Expires: Wed, 19 Jun 2013 16:22:58 GMT Date: Wed, 12 Jun 2013 16:23:03 GMT Connection: keep-alive
If you see Access-Control-Allow-Origin: *
in the response, you're golden!
This same strategy is used by Bootstrap CDN, so you know it's good!
Great tip, thanks. You might clarify however that it’s not so much that Firefox and Internet Explorer “don’t work”, as it is the fact that Chrome and others simply have incorrect defaults when handing CORs. At least that’s my understanding.
Another option is to set your CORS configuration in S3 if you’re planning on using Amazon.
Related: Serve from AWS S3/CloudFront – https://coderwall.com/p/ub8zug
Or for those of use on nginx:
I think it’s important to state that this is an Apache specific approach. We are seeing more and more services such as Node being used as back-end. I see others have already spoken to *nix and S3 solutions but I think is likely a solution available within a pure Node as well.
However, for Node developers I suspect the solution is much less universal and dependant on what’s being used. Connect’s static middleware can probably be overridden to write additional headers for those using anything that includes connect.
Better allow only certain sites/domain instead of * if it is a custom or licensed font (in case of piracy).
Any chance the
@font-face
syntax mentioned by Paul Irish would solve the problem? http://www.paulirish.com/2009/bulletproof-font-face-implementation-syntax/No,
@font-face
would work for fonts hosted on your own server, but not remotely hosted fonts with Amazon S3. Amazon does not send an appropriate CORS header response with the fonts.Thanks for this, you saved me. I found the answer everywhere for the amazon hosting solution, but everyone had failed to mention you can just ad this to the .htaccess file if your hosting somewhere else.
Hello (sorry don’t speak english verry well)
I use on my website CDN (cdn4.kanucomputer.net,cdn5.kanucomputer.net,cdn6.kanucomputer.net) all to my root folder www.
All work with chrome but with IE et FF no icons. My host send my this article to fix the problem, but when I add the code upside in my .htaccess I encounter a “500 internal server error” ???
Someone could help me ?
Thanks a lot.
Have a good day
Same problem:
Additionally, a 500 Internal Server Error error was encountered while trying to use an ErrorDocument to handle the request.
Total htaccess file:
Kevin (and other), i fixed it using this code:
and paste it at the top of your .htaccess file
And it should work.
However, the nginx config fix, should be modified like this aswell. How that works, I would not know.
Cheers
So to be clear, does implementing this .htaccess solution make externally controlled fonts work in IE and FF? Specifically I am building a microsite for a client. I want to pull their fonts from their corporate site to the microsite I will be hosting on a VPS. Currently IE9 is kicking out bugs because of this, and I’m trying to find a good solution.
Thanks for the article. One thing you might want to fix, I noticed the URL to Bootstrap CDN is broken (https://github.com/netdna/bootstrap-cdn/blob/master/.htaccess#L41)
Cheers,
I am using Nginx 1.4 and the configuration has changed a bit.
Instead of an if, a location is preferred.
For Apache I would recommend this to help prevent internal server error:
You say “List specific domains by comma if you want to serve fonts up to only specific domains.” but you should not use a comma separated list here.
The spec only seems to allow for a space separated list or “*”, but it also notes “In practice the origin-list-or-null production is more constrained. Rather than allowing a space-separated list of origins, it is either a single origin or the string “null”.”
See:
http://www.w3.org/TR/cors/#access-control-allow-origin-response-header
https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS#Access-Control-Allow-Origin
For allowing multiple domains see tips at: http://stackoverflow.com/a/1850482/1362634
hello
The Google Fonts is not this displaying in my website.
I used this code but did work, i got (500 internal server error)
I checked for a solution in forums and blogs but it looks like nobody can resolve this issue.
I’m using Hostgator and Cloudflare
Any genius here could help,please
nginx 1.6.* and versions above have deprecated variable:
$filename
you may replace it with variable:
$request_uri
Thanks for the code. You saved me!
Assuming http://www.example.com & cdn.example.com are different web servers. Which is appropriate
1) cdn responds with
Access-Control-Allow-Origin www.example.com
;2) www response with
Access-Control-Allow-Origin cdn.example.com
;On Hiawatha webserver in VirtualHost sections :
Im running nginx and ive tried adding above to htaccess file however I get a 500 internal server error no matter what I try. Any ideas to fix this so that the icons show up on my wordpress site?
Thanks.
You should add
woff2
to the regexp.@clemos – thanks. Got it working now!
Thanks for the help. Saved a lot of time troubleshooting a mess. I know this was written over a year ago. Looks like webkit finally caught up and now no longer supports CDN fonts.
Since we are checking via curl, might as well confirm the server is in fact sending in compressed format
if you do not see gzip or deflate in the response, then you have some more fun quick fixes to make.
Thank you very much for this
For Microsoft IIS7, merge the below into your web.config file located at the root of your application or site (eg: WWWROOT):
If you have a web.config file, merely insert the missing section (eg: customHeaders). Be sure to include the ENTIRE section block.
If you don’t have a web.config file already, simply create a new file called “web.config” in the wwwroot directory with the above contents.
Not wanting to be a hater or anything but it’s worth a note of caution here. It’s generally considered bad security practice to load assets from 3rd parties as you have no control over them so if one of those 3rd parties was compromised, you might end up serving malware etc. Just worth bearing in mind is all I’m saying.
@Neil, agreed. However, in my client’s case, they have a WordPress site with a single domain. The client leverages Vimeo PRO account where their videos are hosted and “included” into the WordPress site via Vimeo APIs. Moreover, the client’s site leveraged Google Fonts.
All was well, until we added a second domain (alias). Neither the Vimeo videos would load nor did the Google Fonts work, until I added the aforementioned (my prior post) enhancement to the web.config file.
Nginx RegExp is quite strange, it gives false positives. Are you sure you didn’t mean:
?
This is just perfect!
Please add how to purge the files from amazon cloudfront (/* for all files, etc) so that it helps people!
And don’t forget to clear the cache before testing any change!
My server is nginx, I don’t think it works for me from any of them..
It’s wordpress site with mutiple language plugin polylang. default domain is english page, sub domain is for foreign.
Could you please pass me the ultimate code?
I got this 500 errors.
Internal Server Error
The server encountered an internal error or misconfiguration and was unable to complete your request.
Please contact the server administrator, postmaster@hermadeals.com and inform them of the time the error occurred, and anything you might have done that may have caused the error.
More information about this error may be available in the server error log.
Did you ever get this resolved? I have the exact some issue:
Great post, thanks.
You may consider to fix the broken mime type of the font. For Apache web-server use:
To fix mime type on Nginx or using PHP see:
http://zinoui.com/blog/cross-domain-fonts
This should work for wildcarding subdomains for apache’s httpd.conf:
…just in case you want to explicitly allow from a single domain instead of *
Tanks this work for me
Thank you so much for this ! it was really helpful.
If I’m a total newb and don’t know how to access my header file, what should I do? The site I’m working on is a simple WordPress theme. (Fonts are loading with you visit http://lsva.org, which is actually being redirected.)
Thanks!
Thank you thank you thank you! Worked perfectly!
Hi,
We are using https://fast.fonts.net/jsapi/f6de1715-1efa-4a83-b5d7-8784f9c21d4a.js in our code base, but this is breaking our website on IE11 and the same works on other browsers.
Please suggest what can be done in this case.
Thanks,
Neeraj
Thank you David! Worked perfectly!
This is a good article, but REALLY doesn’t help if you have no idea what you’re doing. Maybe have another article for noobs? thanks.
If you don’t know what your doing you should NOT be wildcarding Access-Control-Allow-Origin as it is a security vulnerability. See http://blog.portswigger.net/2016/10/exploiting-cors-misconfigurations-for.html
Access-Control-Allow-Origin: * seems kind of dangerous. If effectively breaks same origin protections. Shouldn’t the advice be to limit the control to the origin needed?
For example, I don’t need Access-Control-Allow-Origin: * for MathJax and its webfonts located at https://cdnjs.cloudflare.com/ajax/libs/mathjax . Instead, I should use something like:
Could it be that your apache code is slightly wrong? It works, but I think it is more permissive than it should. With
I think the dot means “any number of characters” which end with eot, etc.
Shouldnt the dot be escaped, like so?
so that it means “any sequence of characters that end with .eot” etc.
That’s odd.
Using Polylang w/wildcard subdomains configured, none of this works. No matter what I do, the FA icons will not be displayed.
Even adding
directly in the .htaccess does not solve the problem.