This blog uses external fonts, which are served from http://www.yjl.im/font/. Chromium (5.0) is my main browser and it renders with those fonts correctly. Some time ago, I noticed that Firefox (3.6) didnt render with those fonts but it did download them. I couldnt figure out why Chromium and Opera (10.10) works fine but Firefox doesnt, and its not as if Firefox cant render with fonts because it uses fonts at http://www.yjl.im/. (Internet Explorer (7) doesnt, either, its same reason. But I dont really care about IE)
I suddenly had a guess, a cross-domain thing. So I googled and found the answer, it refers to Web Font linking and Cross-Origin Resource Sharing, my guess was confirmed.
Short story: you cant use a font (in Firefox) which is not at same domain (origin). I think its right for a browser to have such behavior. Some people like stealing stuff.
Anyway, the solution is to add a response header Access-Control-Allow-Origin:
<FilesMatch "\.(ttf|otf|eot)$">
<IfModule mod_headers.c>
Header set Access-Control-Allow-Origin "*"
</IfModule>
</FilesMatch>
If you uses Apache and you do know how to configure your server, the code above is right for you.
However, many people do not have a webserver, if they do, they probably would host a WordPress blog already and wouldnt encounter this issue. Moreover, Google Sites is probably some peoples file hosting options if they user Blogger, you have no way to add a header. So a normal blogger without skill or knowledge or money, probably wouldnt have a chance to use font-face. Say what? Data URI? For Greens sake, dont use that to serve a font.
As for me, I use Google App Engine at http://www.yjl.im (source code, BSD License). You only need to write a code. font.py does the job, the following code is the main part:
class FontFile(webapp.RequestHandler):
# Chromium don't use fonts with text/html as we want.
EXT_TYPES = {
'.otf': 'application/x-font-otf',
'.ttf': 'application/x-font-ttf',
'.eot': 'application/vnd.ms-fontobject',
'.svg': 'image/svg+xml',
'.js': 'application/x-javascript',
'.woff': 'application/octet-stream',
}
def get(self, fontpath):
fontpath = os.path.normpath(fontpath)
# Does someone try to get other files?
if fontpath.startswith('.') or fontpath.startswith('/'):
self.error(403)
return
# Is requested file a font file?
ext = os.path.splitext(fontpath)[1]
if ext not in FontFile.EXT_TYPES.keys():
self.error(403)
return
fontpath = 'font/%s' % fontpath
# Does this font exist?
if not os.path.exists(fontpath):
self.error(404)
return
if 'Origin' not in self.request.headers:
self.response.headers.add_header('Access-Control-Allow-Origin', 'http://www.yjl.im')
elif os.environ['SERVER_NAME'] == 'localhost' or \
self.request.headers['Origin'] in ['http://www.yjl.im', '']:
self.response.headers.add_header('Access-Control-Allow-Origin', self.request.headers['Origin'])
else:
self.response.headers.add_header('Access-Control-Allow-Origin', 'http://www.yjl.im')
self.error(403)
return
self.response.headers['Content-Type'] = FontFile.EXT_TYPES[ext]
expires = datetime.datetime.utcnow() + datetime.timedelta(365)
self.response.headers.add_header('Expires', expires.strftime("%d %b %Y %H:%M:%S GMT"))
self.response.headers['Cache-Control'] = 'public, max-age=%d' % (86400 * 365)
f = open(fontpath)
self.response.out.write(f.read())
f.close()
The code is fairly simple. First, it checks to make sure no one is trying to do something bad. Then it check the Origin of request header (if client browsers sends it) to see if it is an allowed source. If the request is from an allowed source, then it sets the Access-Control-Allow-Origin to be Origin of request header, same value. Why? Because Access-Control-Allow-Origin can only have one origin assigned, this is the only way to have multiple-origin. Of course you can use *, but that means You are all welcome to hotlink my fonts!.
If its not an allowed source, it sets to http://www.yjl.im and returns 403 status code because its obviously not from allowed source. You can be more creative, serving a special font. ;)
If client browser doesnt send Origin (Chromium doesnt send it), then it sets the header to http://www.yjl.im and sends the font file.
As you can see, I also assign a proper Content-Type. Chromium wouldnt use the font if you dont tell it the right type. (But it doesnt care about cross-origin)
The fonts I use are all downloaded from Font Squirrels font-face Kit. I dont know much about EOT (Embedded OpenType), but I think the EOT from kit are only allowed to use from same origin. Access-Control-Allow-Origin also works for those EOTs from kit, IE didnt use external fonts but it did after I started to use that header.