Ever since the troubles brought on by using Cufon I ventured away from using external font resources, but as of late, I have been looking for alternate methods of loading fonts to see if there's a better way; better methods have a way of just appearing out of the blue.
There are a lot of new methods out there, and variations for each method it seems; Should I use typekit? or google webfonts (with js or css)? should I continue to use locally loading fonts (e.g. fontsquirrel.com generated method)?
I'll list the methods that seem the most well received below, with some tests, but is it really worth moving to a webfont? It seems like it would carry a higher resource load (http requests) and have less file format types (less compatibility) etc. But looks like files are loaded async and efficiently in most cases.
Is it just a matter of situation and need? If so, what are they? Are there drastic differences between these methods? Is there a better method out there I haven't listed? What are the pro's/con's for performance? Look? dependencies? compatibilities?
I'm really looking for best practices here, performance is a big thing but so is scalability and ease of use. Not to mention, look and feel.
Google CSS
only uses external stylesheet
only uses smallest compatible file type
can use @import or or take the contents of the styleshee (@font-face) and put it directly into your own stylesheet.
test results
78ms load of html 36ms load of css
https://i.stack.imgur.com/ARy4Y.jpg
Google JS Method
uses webfont.js to load styleshet
only uses smallest compatible file type
appends :root element with class
adds script to head.
test results
171ms load of html 176ms load of js 32ms load of css
https://i.stack.imgur.com/E6eCr.jpg
Typekit method
appends :root element with class.
can use *.js snippet or externally loaded file *.js file
uses data:font/opentype instead of font file.
adds script to head
adds embedded css to head
adds external stylesheet to head you can easily add/remove/adjust fonts and targetted selectors from typekit.com
test results
169ms load of html 213ms load of js 31ms load of css 3ms load of data:font/
https://i.stack.imgur.com/gEVPu.jpg
…& the Font Squirrel Method
@font-face{
font-weight:400;
font-style:normal;
font-family:open_sanslight;
src:url(../font/opensans-light-webfont.eot);
src:url(../font/opensans-light-webfont.eot?#iefix) format(embedded-opentype),
url(../font/opensans-light-webfont.woff) format(woff),
url(../font/opensans-light-webfont.ttf) format(truetype),
url(../font/opensans-light-webfont.svg#open_sanslight) format(svg)
}
…or with data:font method…
@font-face {
font-family: 'open_sanslight';
src: url('opensans-light-webfont-f.eot');
}
@font-face {
font-family: 'open_sanslight';
src: url(data:application/x-font-woff;charset=utf-8;base64,d09GRgABAAAAAF4sABMAAAAArXQAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAABGRlRNAAABqAAAABwAAAAcZLn0KkqwK44Jq866WBSpzpsNY2IyGAhoJFBbYjuxmyns5sNa4NwldcJ7eh3Uy5gQkURIlqWzONe3HcLsDX1x/+jifDXvbzgTBjopZElndil3hJkERJkmRJkVRJk3TJkEzJkmzOc4HLXOEOF7nEX/*thisisnotafullencodingjustanexample*/bZwUnK4yS3JlTx2Sr4USKEUSbHVX9fcGNBs4fqgw+GoNHU7lKr36Eqn0lCWt6pHFpWaUlc6lS6loSxRlirLlP/uuU01dVfT7L6gPxyqraluCpgj3WtqeC1V4VBDW2N4K1r1esw/IupKp9L1FwlqnuIAAAB42j3NvQ7BUBjG8R5tTz/0u2UjNTTESYQbMGmXLiISbeI6zBYjbuWtye7CeMJxtuf3LP8ne1+IXbWa7G3TMXZru4qLZkJRW1O2wzi3I+Li2Gik5yXpYkNGXj70YU98YQLGHxwwXxIWwO8SNmAdJBzAXku4gFNI9AF38QMjTwZ9vN6yJzq9OoEB6I8VQzDYK0ZguFKMwWiumIDxTDEFk6liBqaF4gDMFFvKxAfOxFUGAAABUxSL9gAA) format('woff'),
url('opensans-light-webfont-f.ttf') format('truetype'),
url('opensans-light-webfont-f.svg#open_sanslight') format('svg');
font-weight: normal;
font-style: normal;
}
<link href='http://fonts.googleapis.com/css?family=Open+Sans:300' rel='stylesheet'>
Georgian
webfonts. I'm using font-squirrel method, and I would like to see a great answer to this question too.
@font-face
declarations, maybe you can find useful informations. paulirish.com/2009/bulletproof-font-face-implementation-syntax
First, I'll clear something up about Google's offering. It will actually load the smallest format your browser can handle. WOFF offers small file sizes, and your browser supports it, so it's the one you see. WOFF is also fairly widely supported. However, in Opera for example, you'll probably get the TrueType version of the font.
The file size logic is also, I believe, why Font Squirrel tries them in that order. But that is mostly speculation on my part.
If you're working in an environment where every request and byte counts, you'll have to do some profiling to find out which works best for your use case. Will people be only viewing one page, and never visiting again? If so, caching rules don't matter as much. If they're browsing or returning, Google might have better caching rules than your server. Is latency the bigger problem, or bandwidth? If latency, aim for fewer requests, so host it locally and combine files as much as possible. If bandwidth, go with whichever option ends up with the smallest code and smallest font format.
Now, on to the CSS vs JS consideration. Let's look at the following piece of HTML:
<head>
<script type="text/javascript" src="script1.js"></script>
<link rel="stylesheet" type="text/css" href="style1.css" />
<style type="text/css">
@import url(style2.css);
</style>
<script type="text/javascript">
(function() {
var wf = document.createElement('script');
wf.src = 'script2.js';
wf.type = 'text/javascript';
wf.async = 'true';
var s = document.getElementsByTagName('script')[0];
s.parentNode.insertBefore(wf, s);
})();
</script>
</head>
In many cases, script1
, style1
, and style2
would be blocking. This means the browser can't continue displaying the document until that resource has loaded (although modern browsers fudge this a bit). Which can actually be a good thing, especially with stylesheets. It prevents a flash of unstyled content, and it also prevents the giant shift that would occur when applying the styles (and shifting content is really annoying as a user).
On the other hand, script2
wouldn't be blocking. It can be loaded later, and the browser can move on to parsing and displaying the rest of the document. So that can be beneficial too.
Specifically talking about fonts (and even more specifically, Google's offering), I would probably stick with a CSS method (I like @import
because it keeps styling with the stylesheet, but that could be just me). The JS file loaded by the script (http://ajax.googleapis.com/ajax/libs/webfont/1/webfont.js) is larger than the @font-face
declaration, and just looks like a lot more work. And I don't believe loading the actual font itself (the WOFF or TTF) is blocking, so it shouldn't delay things too much. I'm not personally a huge fan of CDNs, but the fact is that they're REALLY fast. Google's servers will beat most shared hosting plans by a landslide, and because their fonts are so popular, people might even have them cached already.
And that's all I've got.
I have no experience with Typekit, so I left it out of my theorizing. If there's any inaccuracies, not counting generalizations between browsers for arguments sake, please point them out.
I think you've addressed the load times very well in your question. From my perspective, there are a few sources that should be added to the list, and a few other considerations that should be examined to get a full view of the options.
Some other reputable font sources
cloud.typography
http://www.typography.com/cloud/
From what I can tell, the fonts are embedded as data in a CSS file:
@font-face{
font-family: "Font Name";
src: url(data:application/x-font-woff;base64,d09GRk9UVE8AACSCAA0AAAAARKwAAQAAAAAiVAAAAi4AAAadAAAAAAAAAABDRkYgAAAIyAAAFCgAABmIK5m+CkdERUYAABzwAAAAHQAAACAAXQAER1BPUwAAHRAAAAQlAAAYAq+OkMNHU1VC ... );
font-weight:400; font-style:normal;
}
Here are my specs:
94ms load of css from their server
37ms load of css from our server (will vary based on your configuration)
195ms load of data:fonts from our server (will vary based on your configuration)
Here is their very high-level description of their deployment.
Fonts.com
I haven't used this service, but they're a very established font vendor, and the information they've listed on their site is quite impressive. I don't have specs on their exact methods, but here's what I do know they have:
Some of the most well-known fonts in the world available
A really big font library (over 20,000)
Desktop font downloads for making mockups
A custom tool for testing web fonts in the browser
Fine typography controls and subsetting
Self-hosting options
FontSpring
Affiliated with FontSquirrel. Fonts can be purchased here for a fixed price. The font files an accompanying CSS are delivered, to be deployed on your own server, much like FontSquirrel.
Expanded specs
As to the overall pros and cons of each font service, here are a few comparisons:
Font Library Size
Fonts.com: 20,000+
FontSpring: 1000+
FontSquirrel: 300+
Google: 600+
Typekit: 900+
Typography.com (cloud.typography.com): probably 300+ (35 families)
Pricing
Fonts.com: $20/month for 500,000 page views
FontSpring: Varies by font (one-time purchase of fonts)
FontSquirrel: Free
Google: Free
Typekit: $4/month for 500,000 page views
Typography.com: $12.50/month for 1,000,000 page views
Font Quality
The quality of web fonts can vary quite a bit. This can encompass things like the letterforms themselves or the spacing or the size of the character set. All of these determine the overall impression of quality that a font will give. While the free options have some good options, they also have some fonts that are not as high quality, so you want to choose carefully from those sources.
Fonts.com: High
FontSpring: Mixed to High
FontSquirrel: Mixed
Google: Mixed
Typekit: High
Typography.com: Very high (I give this a "very high" designation because Fonts.com, FontSpring, and Typekit support multiple type foundries, where this is only fonts from the H&FJ foundry, which is among the best in the world)
Font Quality II: Typography
There are a lot of refinements in desktop typography that have been really hard to get in web fonts. Some of these services offer ways of delivering those.
Fonts.com: kerning, letterspacing, ligatures, alternate characters, fractions, etc.
FontSpring: None
FontSquirrel: None
Google: None
Typekit: None
Typography.com: small caps, ligatures, alternate characters, alternate number styles, fractions, etc.
Browser support
This mostly comes down to the font formats that are supported by each service. The major ones are:
EOT: for Internet Explorer (IE 4+)
TrueType and OpenType: Traditional formats (Safari 3.1+, FF 3.5+, Opera 10+)
WOFF: New standard for web fonts (FF 3.6+, Chrome 5+)
SVG: IOS <4.2
More information at The @Font-Face Rule And Useful Web Font Tricks
All of these services support the major font formats. With self-hosted fonts, as long as you use the right syntax you should be covered. Here's a 2011 update of the bulletproof syntax from FontSpring:
@font-face {
font-family: 'MyWebFont';
src: url('webfont.eot'); /* IE9 Compat Modes */
src: url('webfont.eot?#iefix') format('embedded-opentype'), /* IE6-IE8 */
url('webfont.woff') format('woff'), /* Modern Browsers */
url('webfont.ttf') format('truetype'), /* Safari, Android, iOS */
url('webfont.svg#svgFontName') format('svg'); /* Legacy iOS */
}
Performance I: Downloads
As far as I understand it, using the above syntax allows browsers to grab the specific format that works for them, so there's no wasted downloads on font formats that don't work.
The paid services like Fonts.com, Typekit, or Typography.com use methods to detect the correct format and then deliver the right font format, often as base64 data in a CSS file.
From what I can see, the differences in the methods you've listed above are fairly negligible for high-speed internet users (seems like <200ms difference), but could be worth considering for devices on slower networks, especially for uncached page hits.
Performance II: Subsetting
If you know that there will only be certain characters you want to use, you can build your font with a subset of characters and thus reduce the size of the download.
Fonts.com: Very detailed control
FontSpring: Can recompile as subset via FontSquirrel webfont generator
FontSquirrel: Can recompile as subset via webfont generator
Google: Very detailed control
Typekit: limited options of "all characters" or "default"
Typography.com: Very detailed control
Performance III: Delivery
Fonts.com: Global CDN or your own server
FontSpring: Based on your server
FontSquirrel: Based on your server
Google: Global super-CDN
Typekit: Global CDN
Typography.com: Global CDN (125,000 servers)
Language support
Fonts.com: 40 languages, including Asian and Middle Eastern
FontSpring: Western, depending on font
FontSquirrel: Western, depending on font
Google: Western, depending on font
Typekit: Western, depending on font
Typography.com: Western, depending on font
Testing and Implementation
Fonts.com: Very easy, with extensive and customizable tools
FontSpring: Technical (do it yourself)
FontSquirrel: Technical (do it yourself)
Google: Easy
Typekit: Easy
Typography.com: Easy testing, a little more involved to change once deployed
Well, as you are after
... looking for best practices here, performance is a big thing but so is scalability and ease of use. Not to mention, look and feel.
the answer is (like always in web design): It depends!
One thing for sure is, that I would not recommend to use the JS approach (shown in your second example).
Personally I dislike making presentational things and CSS styles depending on Javascript, even though the vast majority of users have it enabled. It is a question of not mixing things up.
And as you can see in your given example there is some kind of FOUC (flas of unstyled content), because the page is already rendered by the browser before the font is available. As soon as it is, the page is redrawn. And the larger the site the larger the (performance) impact!
So I would never ever use any JS solution for fonts embedding.
Now let's have a look at the pure CSS methods.
Since quite a while here is a discussion about " vs. @import". Personally I prefer to avoid the use of @import and always use <link>
only. But this is mainly a question of personal preferences. The one thing you should never do indeed is to mix them both!
Local vs. CDN When deciding if to host your font files locally or use a CDN, then imho it mostly depends on the number of different fonts and the respective fonts you want to embed.
Why is this important, or plays a role? From the performance point of view, I would recommend to include the font Base64 encoded in your (one) style sheet. But only the .woff format, as this is used by nearly all modern browsers, which means for the majority of your visitors. For all other users live with the additional request.
But due to the "overhead" caused by Base64 encoding and the size of a font file (even in .woff format) this technique should only be used, if you have not more than 3 or 4 different fonts. And always make sure, that your server delivers the (CSS) files gzip'ed.
The big advantage of doing so is that you don't have an additional request for the font file. And after the first page load (no matter which page of your site) the CSS file is cached. This is also an advantage if you use the HTML5 application cache (which you certainly will do).
Beside the fact, that an author shouldn't use more than a maximum of 3 or 4 different fonts on his site, let's have a look at the method of using Google's CDN.
First of all be aware, that you can (and always should) include all desired fonts into one single <link>
, like so:
<link href='http://fonts.googleapis.com/css?family=PT+Serif:400,700,400italic,700italic|PT+Sans:400,700,400italic,700italic|Montez' rel='stylesheet' type='text/css'>
This will result in the following response:
@font-face {
font-family: 'Montez';
font-style: normal;
font-weight: 400;
src: local('Montez'), local('Montez-Regular'), url(http://themes.googleusercontent.com/static/fonts/montez/v4/Zfcl-OLECD6-4EcdWMp-Tw.woff) format('woff');
}
@font-face {
font-family: 'PT Sans';
font-style: normal;
font-weight: 400;
src: local('PT Sans'), local('PTSans-Regular'), url(http://themes.googleusercontent.com/static/fonts/ptsans/v6/LKf8nhXsWg5ybwEGXk8UBQ.woff) format('woff');
}
@font-face {
font-family: 'PT Sans';
font-style: normal;
font-weight: 700;
src: local('PT Sans Bold'), local('PTSans-Bold'), url(http://themes.googleusercontent.com/static/fonts/ptsans/v6/0XxGQsSc1g4rdRdjJKZrNBsxEYwM7FgeyaSgU71cLG0.woff) format('woff');
}
@font-face {
font-family: 'PT Sans';
font-style: italic;
font-weight: 400;
src: local('PT Sans Italic'), local('PTSans-Italic'), url(http://themes.googleusercontent.com/static/fonts/ptsans/v6/PIPMHY90P7jtyjpXuZ2cLD8E0i7KZn-EPnyo3HZu7kw.woff) format('woff');
}
@font-face {
font-family: 'PT Sans';
font-style: italic;
font-weight: 700;
src: local('PT Sans Bold Italic'), local('PTSans-BoldItalic'), url(http://themes.googleusercontent.com/static/fonts/ptsans/v6/lILlYDvubYemzYzN7GbLkHhCUOGz7vYGh680lGh-uXM.woff) format('woff');
}
@font-face {
font-family: 'PT Serif';
font-style: normal;
font-weight: 400;
src: local('PT Serif'), local('PTSerif-Regular'), url(http://themes.googleusercontent.com/static/fonts/ptserif/v6/sDRi4fY9bOiJUbgq53yZCfesZW2xOQ-xsNqO47m55DA.woff) format('woff');
}
@font-face {
font-family: 'PT Serif';
font-style: normal;
font-weight: 700;
src: local('PT Serif Bold'), local('PTSerif-Bold'), url(http://themes.googleusercontent.com/static/fonts/ptserif/v6/QABk9IxT-LFTJ_dQzv7xpIbN6UDyHWBl620a-IRfuBk.woff) format('woff');
}
@font-face {
font-family: 'PT Serif';
font-style: italic;
font-weight: 400;
src: local('PT Serif Italic'), local('PTSerif-Italic'), url(http://themes.googleusercontent.com/static/fonts/ptserif/v6/03aPdn7fFF3H6ngCgAlQzBsxEYwM7FgeyaSgU71cLG0.woff) format('woff');
}
@font-face {
font-family: 'PT Serif';
font-style: italic;
font-weight: 700;
src: local('PT Serif Bold Italic'), local('PTSerif-BoldItalic'), url(http://themes.googleusercontent.com/static/fonts/ptserif/v6/Foydq9xJp--nfYIx2TBz9QFhaRv2pGgT5Kf0An0s4MM.woff) format('woff');
}
As you can see, there are 9 different font files, which means a total of 10 (including the one of the link element) requests, if the user does not have one or more of the requested fonts installed locally. And these requests are repeated at every single new page request to your site (although no more data is transferred)! Also the response to the request of the <link>
is never be cached.
Recommendation: After all I really would recommend to include your font file(s) in .woff format Base64 encoded in your style sheet!
See this nice article for an example and description of how to do it!
I use the inline css method because the overhead of the extra request is more than the size increase when bease64 encoding. This is also further offset by gizip compression by the server of the css files.
Other option is to use asynchronous loading of fonts but most often users will see the fonts popping in after load.
Regardless of the method, you can reduce the size of the font file by only including the character sets you will use.
Personally I use Google Fonts. They have a nice variety of choices and they have recently improved compression on the fonts by moving to Zopfli compression too. Google is striving to make the web faster, so I guess more optimization on that part is going to come from them as well.
Whatever you choose as an outsourced font delivery, you will always get reductions in speed by the requests for getting the fonts. The best thing, viewed from a speed perspective, would be to serve the fonts yourself. If you do not care for those extra milliseconds it takes to load from an outsourced delivery, you should go with that if you think the ease of using them is worth the milliseconds.
I do not know about Typekit and the others, but with Google Fonts you can choose to be served specific subsets and range of characters to speed up the delivery even more.
Choosing a subset:
<link href="http://fonts.googleapis.com/css?family=Open+Sans&subset=latin" rel="stylesheet">
Choosing a range of characters:
<!-- Only serve H,W,e,l,o,r and d -->
<link href="http://fonts.googleapis.com/css?family=Open+Sans&text=HelloWorld" rel="stylesheet">
You can use dns-prefetch to improve speeds even further with font delivery.
I do think, and hope, that Google will do all they can to speed up their font delivery as much as they can. The milliseconds it takes to load them doesn't hurt my website, so I happily use them.
Long story short:
If the milliseconds font delivery takes are hurting your site, for example by making it load more than the recommended 1 second, I think you should host them yourself.
<link rel=dns-prefetch href='//fonts.googleapis.com'>
I use it for analytics, heat-mapping, and subdomains, for some reason it didn't register to run for the external webfonts. And the load time greatly differs from font to font, I suppose if you're using a fairly popular font (may be cached) or only a select a handful of fonts, using webfonts is a great fairly quick font source. I'll post tests in speed here shortly.
The best options is to import the fonts using ajax, just like this:
<script>
(function() {
var font = document.createElement('link');
font.type = 'text/css';
font.rel = 'stylesheet';
font.href = '/url/to/font.css';
var s = document.getElementsByTagName('link')[0];
s.parentNode.insertBefore(font, s);
})();
</script>
I do this on my webpage and increase 9 points in the Google Insights test.
async
attribute? It does the same thing.
Success story sharing