@font-face and performance
Last week I was reading Ajaxian (my favorite blog) and saw the post about @font-face. I had been wondering for a few months about how font files impact web performance, so I followed the story back to Zoltan Hawryluk’s original post: @font-face in Depth. A great read on the aesthetics, mechanics, and compatibility issues of fonts, but not much about performance. I added a comment:
How does this impact performance? Do font file downloads happen in parallel with other resources? Are they downloaded at declaration (â€@font-face {}â€), when used in a style (â€body { font-family: }â€), or when a DOM element uses a style that uses the font? Do they follow the normal HTTP caching behavior? Can they be gzipped?
I started doing some research to answer these questions, but during that time there have been a number of great posts about @font-face performance issues:
- Paul Irish: Fighting the @font-face FOUT
- Stoyan Stefanov: Gzip your @font-face files
- Zoltan Hawryluk (again): More @font-face fun
This blog post summarizes Paul, Stoyan, and Zoltan’s findings plus some very important discoveries of my own.
FOUT: Flash of Unstyled Text
Paul refers to FOUT as the “flash of unstyled text”. This is a nod to the term FOUC coined by David Hyatt for “flash of unstyled content”. FOUC occurs when stylesheets are loaded late in the page. (FOUC is the justification for Rule 5 – Put Stylesheets at the Top from High Performance Web Sites.)
Paul comments on two versions of FOUT:
- re-rendered text – Firefox renders text using a default font while the @font-face file is being downloaded. Once the font file is downloaded, Firefox re-renders the text using the correct font.
- invisible text – Most other browsers don’t draw the text at all until the font is downloaded.
I found an even worse FOUT issue:
- IE doesn’t render anything in the page until the font file is done downloading.
- IE doesn’t render anything in the page until the font file is done downloading if there is a SCRIPT tag above the @font-face declaration.
My examples all have a SCRIPT tag at the top of the page containing code for measuring the page load time. This is what causes rendering to be blocked in IE. The fix is simple – make sure all SCRIPT tags are below the @font-face declaration. Using the IE Fix test page, you can see that the page renders immediately. After the font file is done downloading (six seconds), the stylized text is re-rendered. Using this fix brings IE on par with Firefox.
But this IE behavior is still an issue that the IE team should try to fix. A quick survey shows that seven of the Alexa U.S. top ten web sites have a SCRIPT tag above their stylesheets or STYLE blocks: AOL, Facebook, Google, Bing, MSN, MySpace, and Yahoo!. These web sites don’t currently use @font-face, but if they did, they would experience the IE blocked rendering problem. This raises the concern that other web sites that are early adopters of @font-face have a SCRIPT tag above @font-face and their IE users run the risk of experiencing blocked rendering.
You can see this using my FOUT Test where the font file takes six seconds to download – in IE the entire page is white until six seconds pass, even though the HTML text and other parts of the page already arrived at the browser. (This is critical when considering outage scenarios – see the @font-face Outage section that follows.)
All of these FOUT situations are bad for the user experience. It’s jarring for the user to have parts of the page appearing or changing while they view it. And it’s not just the @font-face text that’s the problem – all browsers except IE will likely have to re-render other parts of the page if the default font and @font-face font are different sizes.
FOUT doesn’t impact web page performance in terms of absolute load times, but it does affect the user’s perception of page speed, and that’s what we’re really trying to optimize.
Blocking Other Downloads
When it comes to the question of whether font files block other downloads, the short answer is “no”. I created the Blocking Test to measure whether font files block other resources from being downloaded. The test page contains some text that uses a font downloaded via @font-face. This text is followed by an image, an iframe, a stylesheet, and an external script. Each of these four resources as well as the font file are configured to take two seconds to download. In all major browsers, the page loads in two seconds, meaning no files were blocked.
Note that font files are subject to the same connections-per-hostname limits as other resources. Run the Per Hostname Test to see the limits for your browser. In the Blocking Test, I sharded the resources across multiple domains to avoid any connection limits. But if font files were served from the same domain as other resources, then blocking could occur if the connections-per-hostname limit was exceeded.
Browser Busy Indicators
Although font files don’t block other downloads, they do trigger the browser’s busy indicators. This has a negative effect on the user’s perception of page speed because it gives the impression that the page takes a long time to load. The busy indicators that are triggered vary by browser, according to the following table.
Browser | Status Bar | Progress Bar | Icon | Cursor |
---|---|---|---|---|
IE7 | X | X | X | |
IE8 | X | X | X | |
Firefox 3.5 | X | X | X | |
Safari 4 | X | X | X | |
Chrome 3 | X | X | X |
Note that font files block the window’s onload event from firing in IE and Firefox, but not Safari nor Chrome. This is seen by running the FOUT Test – the page load time is six seconds for IE and Firefox, a few hundred milliseconds for Safari and Chrome.
Wasteful Downloads
Paul credits Garrick from Kernest for pointing out that IE is a little jumpy when it comes to downloading fonts. IE starts downloading the font file as soon as it encounters the @font-face declaration. This means IE downloads the font file even if no elements in the page use the font.
You can verify this with my Unused Font Test. This page has an @font-face declaration, but nothing in the page uses the font. In this page, the font file is configured to take six seconds to download. Sure enough, the overall page load time in IE is six seconds, indicating that the font file was downloaded even though it’s not used. Perhaps IE adopted this approach to avoid the FOUT problem, but given the likelihood of @font-face occurring even if the font isn’t used in the current page, this behavior is likely to result in many wasteful downloads and an overall degradation in performance.
Compression
Stoyan’s post about gzipping font files is a must read. Paul initially thought this wasn’t possible, and I followed suit. Thank goodness Stoyan did the legwork to show that, in fact, you should compress font files. His survey results show a savings of 40% or more for TTF, OTF, and EOT files. I now have Apache configured to compress my font files.
Caching
Font files are cacheable, just like any other resource. You can see this in the Cache Test. The font file is configured to take six seconds to download, so the first time you visit the page, the load time is a little over six seconds. But the font file has a far future Expires header, so clicking on the Cache Test link again happens more quickly since the font file is read from the browser’s cache.
@font-face Outage
Given the FOUT and browser busy issues caused by font files, we need to think about the worst case scenario: What if there’s an issue with the server hosting the font file – what happens if it times out or takes an extremely long time to respond? The Outage Test shows what happens in this situation, and it’s not pretty. The font file in this test is configured to take 20 seconds to download. Here are the results:
- IE: Recall from the FOUT Test that in IE, nothing in the entire page is rendered until the font file is done downloading. This is true even if the @font-face style is below everything else in the page. If you load the Outage Test in IE, nothing will render for 20 seconds. Ouch!
- In Firefox, the text is drawn in a default font, then redrawn once the font file is downloaded after 20 seconds.
- In most other browsers, the text isn’t drawn for 20 seconds, but the rest of the page is rendered.
Prompted by Annie Sullivan, I tried to find the maximum time a browser would spend trying to download a font file. The maximum download time I tested was 10 minutes. Safari did the best: after 60 seconds it bailed and rendered the stylized text with a default font. IE did the worst: with a 10 minute download time, IE still showed a blank white page. Firefox drew the text in a default font immediately (its normal behavior), but its busy indicators continued to agitate for 10 minutes. Chrome never rendered the text, and its busy indicators continued for the full 10 minutes.
These slow response and outage issues raise significant concerns for anyone considering using @font-face. It’s different from what happens when an image times out and the page ends up showing the broken image icon. If a font file fails to return, the page is blocked in IE, the text isn’t displayed in Chrome, and the browser’s busy indicators never stop in IE, Firefox, and Chrome (at least for 10 minutes).
@font-face Performance Advice
My first piece of advice is to avoid using @font-face unless it’s critical to the page.
The primary reason for this advice is the risk that font files will block rendering of the entire page in IE until they’re done downloading if there is a SCRIPT tag above the @font-face declaration. Stylesheets also have this blocked rendering problem. But stylesheets provide styling for all aspects of the entire page, whereas font files only add one thing – a custom font.
If you’re not deterred by the FOUT and outage issues, and want to push on to use @font-face, I recommend deferring the font file download until after the page has rendered, as shown in the Lazy Load Test. This solves the issues in IE – the page renders and then the font is downloaded in the background and enhances the stylized text once it arrives. This technique has benefits in other browsers, as well. By lazy loading the font file, most of the browser busy indicators aren’t triggered. The lazy load code looks like this:
function lazyload() { var sRule1 = "@font-face {" + " font-family: 'Yanone';" + " src: url('/bin/resource.cgi?type=font&sleep=6');" + " src: local('Yanone'), " + "url('/bin/resource.cgi?type=font&sleep=6') " + "format('truetype');" + "}"; var style1 = document.styleSheets[0]; if ( "function" === typeof(style1.insertRule) ) { // Firefox, Safari, Chrome style1.insertRule(sRule1, 0); } else if ( "string" === typeof(style1.cssText) ) { // IE style1.cssText = sRule1; } }
This is a prototype, not a hardened solution. There are shortcuts here (styleSheets[0] is an empty style block in the page). In Safari and Chrome there is a slight flash of the stylized text. I talk about some possible workarounds in the test page itself.
In Paul’s post he talks about prefetching font files, but notes that the technique doesn’t apply to IE. I consider IE to be the most significant problem to solve. Also, I would tend to put stylesheets and scripts, and in some cases images, at a higher priority to download than font files. It depends on the page and how the font file is used.
I don’t recommend using data: URIs in place of the font files in stylesheets. That could double the amount of data that was downloaded, since the stylesheet would have to contain the data for both the EOT and TTF files. This would also make stylesheets take longer to download, and stylesheets block rendering in almost all browsers.
Summing up:
- Only use @font-face if you’re absolutely certain you need it.
- Put your @font-face declaration above all SCRIPT tags.
- If you have multiple font files, consider sharding them across multiple domains.
- Don’t include unused @font-face declarations – IE will download them whether they’re used or not.
- Gzip the font files and give them a future Expires header.
- Consider lazy loading the font files, at least in IE.
Given the high number of posts about @font-face recently, I expect we’ll see more performance issues and workarounds as we grapple with how to use this feature in today’s browsers while ensuring our users get the fast experience they want and deserve.
Kieran Hall | 13-Oct-09 at 1:33 am | Permalink |
I wonder whether we’ll see the likes of Google providing royalty-free font files from their CDN? They could take care of compression and caching and if a ‘critical mass’ is reached, we could really see a speed benefit.
Steve Clay | 13-Oct-09 at 3:56 am | Permalink |
Opera 10: Good: FOUT renders all text w/ no waiting indicator. Bad: @font-face does block image/iframes and, after that page, @font-face stopped working altogether for any of the test pages!
Paul Irish | 13-Oct-09 at 4:22 am | Permalink |
Adam Twardoch of FontLab just posted some test pages looking at subsetting. (Subsetting whole character sets into multiple files, recombining in the font stack)
http://www.twardoch.com/webfonts/
It’s an interesting look at browser support as well as confirming that even IE8 cannot do data: URIs. (I’ve also been unable to get IE to use MHTML to serve the font data.
Roger Black | 13-Oct-09 at 4:44 am | Permalink |
Of course if we all “avoid using @font-face unless it’s critical to the page”, the browsermakers will never fix the problems. We’ve had @font-face for 10 years, but with no common font solution, there was no demand, and without demand, the browsers didn’t have to deal.
Now there is demand!
We have to hammer on their doors to get the download issues solved, and to get a single web font standard.
– – – –
PS: What about downloading for every page, which the browsers seem to do. Once a font downloaded, the browsers should cache them on the likely chance they will be used again in the session.
Jonathan Hoefler | 13-Oct-09 at 5:03 am | Permalink |
Thank you for taking the time to research this and write about it, Steve — this is a really useful collection of observations.
Roger, to your “PS: What about downloading for every page,” oh where to begin…
garrick van buren | 13-Oct-09 at 5:09 am | Permalink |
Kieran Hall – http://kernest.com is currently serving >600 free font files with that goal in mind.
Brett Bergeron | 13-Oct-09 at 6:02 am | Permalink |
Roger – Referencing the font face on a third-party domain, if adopted widely by designers, can help alleviate bandwidth stress. The idea is that browsers cache a file called from a CDN, such as Google, and it can be quickly recalled when referenced on another website. It’s a trick that helps create a cross-site cache.
Google has been encouraging this practice for Javascript: http://code.google.com/apis/ajaxlibs/
Kernest.com seems to be have a similar idea in mind.
Matt | 13-Oct-09 at 7:19 am | Permalink |
“IE downloads the font file even if no elements in the page use the font.”
Probably so the first AJAX call that requires it doesn’t hang the page for 6 seconds while it downloads, etc. As you pointed out in the caching section, it’s a one-time hit. May as well get it done up front to reduce user frustration.
Manuel Razzari | 13-Oct-09 at 7:54 am | Permalink |
Just a minor clarification:
FOUC was actually coined in 2001 by Rob Chandanais, AKA BlueRobot at http://bluerobot.com/web/css/fouc.asp/
Thomas J Bradley | 13-Oct-09 at 8:11 am | Permalink |
You mentioned serving the font files from alternate domains. I have found that Firefox doesn’t always download fonts on alternate domains.
I have tried sub domains but to get fonts to download reliably with Firefox’s same domain policy the fonts seem to need to be on exactly the same domain.
Nathan Youngman | 13-Oct-09 at 8:34 am | Permalink |
Thanks for the insight Steve. I wonder how this compares to other custom font solutions, performance-wise. I would think something like Cufon would have the same loading properties as regular JavaScript, plus they have some recommendations to combat FOUT in IE.
Of course Cufon is not without its limitations, no copy-paste, no editing. I also haven’t tried it with a large amount of text. As always, it depends on the use case.
Nathan Youngman | 13-Oct-09 at 8:37 am | Permalink |
@Thomas, my co-worker had the same issue… it sounds a feature to prevent hotlinking other peoples fonts. I believe the solution was to configure Apache with Access-Control-Allow-Origin.
Matt | 13-Oct-09 at 9:02 am | Permalink |
While it might not help in the short run, since we have to deal with the browsers we have, we should probably develop a “best practices” for how browser makers ought to handle @font-face loading.
So, what *should* they do? Safari seems to have a decent solution, except you can’t see the text for a whole minute if it’s slow to download. Perhaps mix of Safari and Firefox, where the browser puts off any text rendering for a short time (two seconds?) to avoid FOUT, but if the font has not loaded by then, use a default font until the download is complete?
Steve Souders | 13-Oct-09 at 9:24 am | Permalink |
@Kieran Hall: I think it would be good to have a widely used font CDN, similar to what Google Ajax Libraries does for popular JS frameworks. Typekit is heading that way.
@Steve Clay: Yes, there’s a bug in Opera. Paul describes this in More @font-face fun.
@Manuel Razzari: Thanks for the corrected citation!
@Thomas J Bradley: I assume there’s a workaround for serving fonts from a different domain in Firefox so that projects like Typekit and Kernest work. Another tact would be to move the *other* resources (images, etc.) to the sharded domain and keep fonts on the main domain.
Steve Souders | 13-Oct-09 at 9:49 am | Permalink |
@Roger Black and @Matt: You’re right, let’s nail down how browsers *should* handle @font-face.
1. FOUT – I agree with the comments from Paul Irish and Remy Sharp in Paul’s blog post. The browser doesn’t render the text while it waits for the font file to download (this is what Safari and Chrome do now). But there’s a short timeout (250ms) after which the text is rendered in a default font. If/when the font file finishes downloading, the text is re-rendered.
2. Timeout – All the browsers need to follow Safari’s lead and terminate requests after 60 seconds. I was surprised to see this indefinite wait also happens for images.
3. Busy Indicators – I would vote that Browsers shouldn’t trigger busy indicators for font files. Or at least should turn them off after a short time (10-60 seconds).
What else?
Paul Irish | 13-Oct-09 at 9:53 am | Permalink |
@Thomas, like Nathan indicated if you’re serving web fonts from a remote domain (even a subdomain) you must use Access Control Allow Origin headers.
In my talk on employing custom fonts, I used a .htaccess code sample like this:
Header set Access-Control-Allow-Origin “your-domain.com”
Paul Irish | 13-Oct-09 at 9:55 am | Permalink |
@Thomas, blog ate my formatting and xml. Here’s the .htaccess snippet.
Thomas J Bradley | 13-Oct-09 at 10:25 am | Permalink |
@Paul and @Nathan: That’s good to know, thanks!
sunnybear | 13-Oct-09 at 11:25 am | Permalink |
Thx for article. One more breakthrough. I would add 2 more things:
1) Automated gzip for fonts can be tricky due to the absense of standard mime types for fonts — see http://www.iana.org/assignments/media-types/
I’ve found several dozens of different approaches for these 3 extensions – otf / ttf / eot (svg seems to be more or less standardized).
2) There is a project – Font Optimizer (perl-based). I think that future is after such utilities – http://bitbucket.org/philip/font-optimizer/src/
Miller Medeiros | 13-Oct-09 at 1:04 pm | Permalink |
besides the performance issue what really makes me not use the @font-face is because some browsers don’t use ClearType for custom fonts.. (on Firefox it looks really bad) so what’s the point of using a different font if it is going to look like cr**?
I will stick to standard fonts and images/flash for heading text.
b°b | 13-Oct-09 at 11:05 pm | Permalink |
FOUT means WRONG in Dutch…
Michael Kozakewich | 13-Oct-09 at 11:23 pm | Permalink |
It’s not reliable, but people could lazy-load the fonts on their main page, but not use the fonts on that page. Not everyone lands on that page, though, which is why it’s also unreliable.
I like the idea of splitting the font into different packages and recombining them. Have a set for letters, numbers, and punctuation, and then a set for the less-common stuff.
John Daggett | 14-Oct-09 at 12:41 am | Permalink |
The flashing sucks but seeing a blank page sucks for a user, especially those not lucky enough to be on a high-speed connection. Even in Safari, if a page is complex enough, the font metrics of a newly downloaded font are going to cause other content to move, since the page is initially rendered using the metrics of a default font.
It’s also possible to emulate Safari behavior in other Firefox/Opera. Add a class declaration to elements using downloadable fonts, then add script in the header to add a style rule for that class that sets visibility to hidden, then remove it within an onload handler. You could also add a handler that fires on a timeout after N seconds to clear the rule so that the default font would be used for users on slow connections.
For Firefox, tracking this issue here:
https://bugzilla.mozilla.org/show_bug.cgi?id=499292
@Roger Black – Fonts are cached, for which browser/OS are you seeing font not being cached? Did you check the access logs to confirm that the entire font is getting downloaded each time? Ex: under Mac OS X, run the Console application and look for apache2 > access_log. If a font is downloading you’ll see something like “200 266448” at the end of the line, reflecting the HTTP response code (200) and the size downloaded (266448).
Xavier Tassin | 14-Oct-09 at 6:43 am | Permalink |
Hi Steve,
On the testing I have done so far, IE seems to behave differently depending on HTTP headers (Content-Encoding, Transfer-Encoding, etc…)
Try the link bellow with a clear cache and see IE loading and displaying first the HTML content while loading the fonts in background:
http://www.keynoise.com/fonts/custom-fonts.html
The FOUT in all it’s glory!
I have no clear explanation yet but I suspect your test case to be biased by gzip compression or HTTP headers returned with your cgi generated font file.
I could observe this in IE 6/7/8
Thanks for the great article.
Boris | 14-Oct-09 at 7:35 am | Permalink |
You can use subdomains for fonts if you send the right Access-Control headers with them. For cross-domain loads, there’s a check in Firefox to make sure that the domain the font is coming from is ok with having its font used on other domains.
Steve, fonts should time out the same way images do, at least in Firefox. Did you try a similar test with an image to see what the 10 minute behavior is there?
Justin | 14-Oct-09 at 8:49 am | Permalink |
Short timeouts might be nice for users and sites on guaranteed fast connections, but that means a slow/busy network or temporary glitch results in broken pages and frustration. Better to let the browser try it’s best than quickly show a broken page for perceived performance.
Steve Souders | 14-Oct-09 at 9:59 am | Permalink |
@Boris: Paul’s earlier comment mentions Access-Control-Allow-Origin. That fixes the problem on subdomains as well as other domains. I added the Cross Domain Test to show this works. To your second point, in my previous comment I mentioned that I tested long loading images and they behave the same. Here’s the Long Loading Image Test.
@Justin: The proposal isn’t to show a broken page – it’s just the opposite. Rather than have the text never appear, it would appear in a default (or secondary) font. That’s a better user experience than never seeing the text at all. For slow loading font files there’s room for debate: is it better to show nothing for 2 seconds or show the default font after 250ms then switch it after 2 seconds? What about 3 seconds? 4? For me, I’d prefer to see a default font quickly even though that raises the probability it’ll flash.
randsco | 14-Oct-09 at 10:55 am | Permalink |
LOL … thanks Paul & Steve for exposing the dark underbelly of @font-face! Nothing on the web is as simple as it should be, eh?
I always thought of IE as handling @font-face “correctly” & the FireFox FOUT as being aptly translated by Dutch! Discovering that IE won’t load anything, if the font file download hangs, is disturbing.
However, I agree with Roger Black. Working around these browser problems won’t hold their makers to task. And neither will sticking to web-safe fonts.
I’m not fond of the ‘lazy load’ technique, as it adds complexity where none should exist and introduces accessibility issues into what should be strictly CSS.
I say damn the torpedoes. Use @font-face as intended and (as with most everything else) let the browser-makers catch up.
Now … on to my math quiz to beat the SPAM blocker! :p
Ethan Dunham | 14-Oct-09 at 12:05 pm | Permalink |
Great research Steve. Thanks for sharing. I realize this is a bit tangental, but I just finished building a @font-face generator… you upload fonts, adjust some settings (subsetting for example) and it’ll spit out a “kit.”
I just tried it on Gentium-Basic, whose average file size is about 270k. I selected English-only glyphs and the size is now around 45k. Definitely helps the FOUT problem!
Font Squirrel @font-face Generator
Steve Souders | 14-Oct-09 at 12:43 pm | Permalink |
@Xavier Tassin: Thanks for catching this!!! This is what blogging is all about. It turns out that IE blocks rendering the entire page IF THERE IS A SCRIPT TAG ABOVE THE @FONT-FACE DECLARATION.
Here’s your test page with an empty script block above the @font-face: Xavier’s modified test case. If you clear your cache and try this in IE you’ll see the entire page get blocked from rendering. (So it’s not headers or gzip or anything.)
This mitigates the IE issue, but how likely is it that a web site has a script tag above its stylesheets or style blocks? 7 of the Alexa US top 10 web sites have a script tag above their stylesheets or style blocks. So this is still a significant issue.
I’m updating this blog post now.
ChrisB | 14-Oct-09 at 2:06 pm | Permalink |
Maybe the problem of text content not beeing rendered at all before the custom font is loaded could be tackled with JavaScript – by “font preloading”
Initially, the content would be formated with a “normal” font in the CSS.
On loading the page, we generate a new Img-object in JavaScript, and set the URL of our custom font as the value of the src-attribute of that image. Of course, the browser will not be able to display the response as an image – but since it’s not part of our document, nothing to bother.
Events like onload or oncomplete should fire on this so called “image” nonetheless – so we could use these to make our script realise, “OK, the font file is completly loaded now”.
And then our script changes the className of the body element, so that some CSS rules using the descendant selector become now “active”, and our content is displayed in our custom font from then on …
So far for my as yet untested theory :-)
I don’t know if it will work out as presented, but maybe someone want’s to give it a try?
Boris | 15-Oct-09 at 7:41 am | Permalink |
Steve, my point was that your text continues to say:
“It’s different from what happens when an image times out and the page ends up showing the broken image icon.”
when in fact it’s not different at all. You do have a correction following the paragraph, but you might want to strike that sentence out too.
As for timing out long-running requests, network stacks _do_ have TCP timeouts. This testcase isn’t hitting them, because the server does in fact keep responding every so often saying “I’m here, I’m here, I’ll send data in a jiffy” (just use tcpdump to watch the packets going by). If the server were actually unreachable, the connection would in fact time out. If you think browsers should override the default OS network timeout behavior with timeouts of their own, that’s a pretty slippery slope…
Richard Fink | 15-Oct-09 at 9:35 am | Permalink |
@steve souders
“My first piece of advice is to avoid using @font-face unless it’s critical to the page.”
Steve, I’ve followed your work, own both your books. I’m a fan. But philosophically, I find this advice simplistic and antithetical to the “can do” spirit of the web.
What’s up?
What do you mean by critical? Under what circumstances would @font-face be so harmful that you would warn people away? (In other words, too broad a brush. IMHO.)
All font files are not necessarily huge. (And that’s the nub, isn’t it?) Right now, on Readable Web I’m using a sub-setted TTF that weighs in at a whopping 25kb uncompressed and getting a lot of design bang for the byte out of it.
@font-face isn’t the swine flu.
As always, test, test, test, before deploying, but don’t avoid!
Please re-think and re-phrase, Steve. Your opinion carries weight.
@Ethan Dunham
Checked out your subsetting page on Font Squirrel. Outstanding. How is it you seem to be the only font distributor going at this with a lick of common sense?
Ethan Dunham | 15-Oct-09 at 10:50 am | Permalink |
@Richard Fink
I guess because they aren’t my fonts? :-) Although, since I am also fonthead.com … I need to do that.
Steve Souders | 15-Oct-09 at 1:40 pm | Permalink |
@Boris: It’s different in that a broken image doesn’t make the entire page blank. Thanks for the pointers about the TCP connection. I’ll try to work on a test that more accurately mimics a timeout.
@Richard Fink: Thanks for buying my books. I hope I don’t drive you away! If a page contains @font-face with a script tag above it, IE blocks rendering of the entire page. Every page that I’ve seen that uses @font-face (that isn’t a test page) has a SCRIPT tag above the @font-face declaration. (This includes your page. ;-) In addition, font files will compete for connections against resources that I consider a higher priority: stylesheets, scripts, and in some cases images. Perhaps “critical” could be rephrased to “really important” or “non-gratuitous”.
Boris | 15-Oct-09 at 5:21 pm | Permalink |
Ah, I agree that in IE the missing or very slow font is a big deal. It seems that it’s not nearly as much of a problem in all the other browsers.
Richard Fink | 15-Oct-09 at 8:26 pm | Permalink |
@steve
Darn, busted by my own site. (WordPress made me do it!)
@font-face obviously has some major performance caveats attached.
But when Firefox >3.5 hits “critical mass” and 90%+ of all browsers support web fonts for many designers the temptation is going to be too great.
So, one thing *is* critical: identifying best practices.
Thanks for helping to tame this beast. It’s a tough one for sure.
FrankyBoy | 19-Oct-09 at 10:38 am | Permalink |
jo, you forgot about opera 10 which has also support for @front-face.
Dan | 22-Oct-09 at 7:55 am | Permalink |
I thought it would be worth noting the interesting work by Mozilla in regards to compressed font files/formats:
http://hacks.mozilla.org/2009/10/woff/
Paul Irish | 08-Nov-09 at 7:46 am | Permalink |
I wrote a short piece of code for the folks that don’t like Firefox’s use of a fallback font:
http://paulirish.com/2009/fighting-the-font-face-fout/#defeatthefout
Albert | 12-Feb-10 at 6:43 am | Permalink |
i always thought bluerobot first wrote about FOUC? Just curious. http://bluerobot.com/web/css/fouc.asp/
John Grimes | 15-Feb-10 at 1:47 pm | Permalink |
TypeFront takes care of compression, caching and access control of embedded font files. Also supports WOFF.
Christopher | 05-Sep-10 at 10:35 pm | Permalink |
Great info Steve. Without going into great detail, I can say that you have solved at least one irritating (and ongoing) problem for me. Thanks for sharing.
Ayyash | 24-Sep-11 at 9:08 pm | Permalink |
I have a question, how about the number of times the font is being used on the page? does that affect performance in any way? thanks.
Steve Souders | 24-Sep-11 at 10:55 pm | Permalink |
@Ayyash: If @font-face is used on more elements in the page then more of the page will be delayed from rendering.
Ayyash | 29-Sep-11 at 7:50 am | Permalink |
yes but the question is the time that lapses until it finally gets loaded, if its 3 seconds of one H1, for 10 H1s, is is it still 3 seconds or does it become 30 seconds?
in other words, if I turn all of my document into an embedded font (delayed binding), would it take longer than usual to finally render?
Ayyash | 30-Sep-11 at 5:36 am | Permalink |
Hey, I think since embedded fonts dont block other downloads it makes sense to assume the number of times it is being used on the page does not affect it… ran a small test to confirm, but just thought I should let you know that IE9 does not behave like IE8, it does render the default fonts until font is downloaded.. so that’s an update i assume?
PS. can u move the captcah field above the submit button :|
Estelle | 22-Jan-12 at 5:19 pm | Permalink |
It’s important to remember that if you don’t need a full font set, you can greatly reduce the file size by selecting the characters to include in your font files. For example, if you’re using a font for your favorite ampersand, include only the ampersand. Or, if you are using it just for drop caps, include just capital letters.
http://www.fontsquirrel.com/fontface/generator, under “expert” allows for custom subsetting, subsetting by language, etc.
Karl Kelman | 19-Feb-12 at 9:37 pm | Permalink |
Think about using jQuery to delay/fade content loading as a method of dealing with FOUT as well.
After some experimentation, I decided that was the best route for me.
Ejaz | 23-Apr-12 at 12:51 pm | Permalink |
Very good article (and comments) but I think now it requires an update. What do you think Steve?
Steve Souders | 23-Apr-12 at 8:31 pm | Permalink |
@Ejaz: I don’t update blog posts once they get this old. You might be interested in newer blog posts that talk about performance issues of font files: Frontend SPOF, Browser Performance Wishlist, and Frontend SPOF in Beijing.
Juri | 06-Jun-12 at 4:50 pm | Permalink |
OK almost done but where should I add the function lazyload?
I’m running a WordPress site and I’m assuming I should add it in the jquery.js file
Thanks for your help
Juri | 07-Jun-12 at 3:23 pm | Permalink |
@Steve please see my comment above. I don’t know jQuery.
Or should I load it in the header in php?
Also instead of the url below should I type my font path? if so should I load the .eot for IE or whatever browser I want to use lazyload?
/bin/resource.cgi?type=font&sleep=6
If you can please advice would be awesome! Thanks
Chris Adams | 26-Nov-12 at 12:12 pm | Permalink |
For anyone else still following this, I’ve found that IE8 blocks even when the @font-face is declared before the first tag as long as any tags are still below the , which broke my attempt to declare only fonts before the html5shiv.
Joe Flash | 01-Mar-13 at 5:21 pm | Permalink |
The issue of any loading JavaScript before any style sheet is addressed in Google’s PageSpeed. Loading the JavaScript first can block the downloading of the CSS files which can download in parallel, preventing the page from rendering sooner.
The functionality of the JavaScript can also be affected by the late rendering of the CSS. The change, or redraw, of fonts can most certainly change the dimensions of containers in the page after the script has started.
This is the big reason why PageSpeed and YSlow recommend placing the CSS in the head before any scripts, and put the JavaScript at the end of the body whenever possible. The page renders sooner with the least chance of the ‘flash’ effect, and the functionality is more reliable.