Waiting for web fonts to load

While working on a project where I was required to sample dimensions of HTML elements with specific web fonts, I have bumped into a problem. There wasn’t any DOM event that signaled that specific fonts are loaded and rendered. Even though all the fonts were base64 encoded and inserted into a web page immediately after XMLHttpRequest response, it didn’t indicated that these fonts were actually rendered and that elements enclosing them received their final dimensions.

After a short research, I have found a hint in typekit’s blog. Their solution was to create off-screen element, one for each font, with a bit of text and appropriate font-family value. Then periodically compare that element width to a reference width. Once element width changes, we can say that font is loaded and rendered.

Because I was only needed for a simple function without 3rd party references I wrote a short function that implements solution described above. This function receives an array of strings representing required font-families and a callback function which invoked when all passed fonts are loaded:

The onFontsLoad function also receives third optional parameter which is an object with two fields:

  1. maxNumOfTries – number of polls for element dimension.
  2. tryIntervalMs – interval in milliseconds between polls.

The function iterates over passed font-families array and creates elements with pangram text and appropriate font-family for each font. It also creates one element with reference “serif” font and stores its dimensions to be used as a reference. The pangram ensures that change in dimension will occur even if dimension of only one alphabetic character of the requested font is different from the reference font. The font-size used on all element is 40px, this is to ensure that even slightly change in font appearance will effect in dimension change. Then, it polls the dimensions of elements, and when all elements changed sizes the callback is invoked. However, if after specific time (maxNumOfTries * tryIntervalMs) some fonts are still not loaded then callback invoked anyway.

The callback is executed with single parameter. If all fonts were loaded, then this parameter will be “null”. Otherwise, this parameter will be an object with “message” property with an error message and addition property named “notLoadedFontFamilies” with an array of font-families that weren’t loaded.

Here is an usage example:

// Show some loading indicator while fonts on a page are loaded
 
onFontsLoad(["myFont1", "myFont2"], function(error) {
    // Hide loading indicator and show elements with loaded fonts
});

comments powered by Disqus