How to be notified once a web font has loaded

Google's Web Fonts API offers a way to define callback functions to be executed if a font has finished loading, or couldn't be loaded etc. Is there a way to achieve something similar using CSS3 web fonts (@font-face)?



2015 Update

Chrome 35+ and Firefox 41+ implement the CSS font loading API (MDN, W3C). Call document.fonts to get a FontFaceSet object, which has a few useful APIs for detecting the load status of fonts:

  • check(fontSpec) - returns whether all fonts in the given font list have been loaded and are available. The fontSpec uses the CSS shorthand syntax for fonts.
    Example: document.fonts.check('bold 16px Roboto'); // true or false
  • document.fonts.ready - returns a Promise indicating that font loading and layout operations are done.
    Example: document.fonts.ready.then(function () { /*... all fonts loaded...*/ });

Here's a snippet showing these APIs, plus document.fonts.onloadingdone, which offers extra information about the font faces.

alert('Roboto loaded? ' + document.fonts.check('1em Roboto'));  // false

document.fonts.ready.then(function () {
  alert('All fonts in use by visible text have loaded.');
   alert('Roboto loaded? ' + document.fonts.check('1em Roboto'));  // true

document.fonts.onloadingdone = function (fontFaceSetEvent) {
   alert('onloadingdone we have ' + fontFaceSetEvent.fontfaces.length + ' font faces loaded');
<link href=',700' rel='stylesheet' type='text/css'>
<p style="font-family: Roboto">
  We need some text using the font, for the font to be loaded.
  So far one font face was loaded.
  Let's add some <strong>strong</strong> text to trigger loading the second one,
    with weight: 700.

IE 11 doesn't support the API. Look at available polyfills or support libraries if you need to support IE:


Tested in Safari, Chrome, Firefox, Opera, IE7, IE8, IE9:

function waitForWebfonts(fonts, callback) {
    var loadedFonts = 0;
    for(var i = 0, l = fonts.length; i < l; ++i) {
        (function(font) {
            var node = document.createElement('span');
            // Characters that vary significantly among different fonts
            node.innerHTML = '[email protected]!-/#';
            // Visible - so we can measure it - but not on the screen
        = 'absolute';
            = '-10000px';
             = '-10000px';
            // Large font size makes even subtle changes obvious
        = '300px';
            // Reset any font properties
      = 'sans-serif';
     = 'normal';
       = 'normal';
      = 'normal';
   = '0';

            // Remember width with no applied web font
            var width = node.offsetWidth;

   = font;

            var interval;
            function checkFont() {
                // Compare current width with original width
                if(node && node.offsetWidth != width) {
                    node = null;

                // If all fonts have been loaded
                if(loadedFonts >= fonts.length) {
                    if(interval) {
                    if(loadedFonts == fonts.length) {
                        return true;

            if(!checkFont()) {
                interval = setInterval(checkFont, 50);

Use it like:

waitForWebfonts(['MyFont1', 'MyFont2'], function() {
    // Will be called as soon as ALL specified fonts are available

The JS Library used by Google Web Fonts API (and Typekit) can be used without the service: WebFont Loader.

It defines callbacks for what you ask, and many more.


2017 Update

The JS library FontFaceObserver is definitely the best, most lightweight, cross-browser solution as of 2017. It also exposes a Promise-based .load() interface.


The window.load event will fire when everything has loaded - that should include fonts So you could use that as the call back. However I don't think you have to is you decide to use the web font loader as

In addition to the google, typekit, ascender and monotype options, there is also a custom module that can load a stylesheet from any web-font provider.

WebFontConfig = { custom: { families: ['OneFont', 'AnotherFont'], urls: [ '', '' ] } };

The library sends the same events regardless of which provider you specify.


Recent Questions

Top Questions

Home Tags Terms of Service Privacy Policy DMCA Contact Us

©2020 All rights reserved.