Webfonts or Locally loaded fonts?

JavascriptCssFontsWebfonts

Javascript Problem Overview


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.

  1. Is it just a matter of situation and need? If so, what are they?
  2. Are there drastic differences between these methods?
  3. Is there a better method out there I haven't listed?
  4. 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 <link> 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

enter image description here


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

enter image description here


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/

enter image description here


…& 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;

}

Javascript Solutions


Solution 1 - Javascript

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.

Solution 2 - Javascript

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

Solution 3 - Javascript

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!

Solution 4 - Javascript

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.

Solution 5 - Javascript

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.

Solution 6 - Javascript

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.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestiondarcherView Question on Stackoverflow
Solution 1 - JavascriptZachRabbitView Answer on Stackoverflow
Solution 2 - JavascriptnwaltonView Answer on Stackoverflow
Solution 3 - JavascriptNetsurferView Answer on Stackoverflow
Solution 4 - JavascriptChris GunawardenaView Answer on Stackoverflow
Solution 5 - JavascriptJeremy KarlssonView Answer on Stackoverflow
Solution 6 - JavascriptPhok7View Answer on Stackoverflow