Last active
October 9, 2024 00:35
-
-
Save hdragomir/8f00ce2581795fd7b1b7 to your computer and use it in GitHub Desktop.
The deferred font loading logic for Smashing Magazine. http://www.smashingmagazine.com/
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<script type="text/javascript"> | |
(function () { | |
"use strict"; | |
// once cached, the css file is stored on the client forever unless | |
// the URL below is changed. Any change will invalidate the cache | |
var css_href = './index_files/web-fonts.css'; | |
// a simple event handler wrapper | |
function on(el, ev, callback) { | |
if (el.addEventListener) { | |
el.addEventListener(ev, callback, false); | |
} else if (el.attachEvent) { | |
el.attachEvent("on" + ev, callback); | |
} | |
} | |
// if we have the fonts in localStorage or if we've cached them using the native batrowser cache | |
if ((window.localStorage && localStorage.font_css_cache) || document.cookie.indexOf('font_css_cache') > -1){ | |
// just use the cached version | |
injectFontsStylesheet(); | |
} else { | |
// otherwise, don't block the loading of the page; wait until it's done. | |
on(window, "load", injectFontsStylesheet); | |
} | |
// quick way to determine whether a css file has been cached locally | |
function fileIsCached(href) { | |
return window.localStorage && localStorage.font_css_cache && (localStorage.font_css_cache_file === href); | |
} | |
// time to get the actual css file | |
function injectFontsStylesheet() { | |
// if this is an older browser | |
if (!window.localStorage || !window.XMLHttpRequest) { | |
var stylesheet = document.createElement('link'); | |
stylesheet.href = css_href; | |
stylesheet.rel = 'stylesheet'; | |
stylesheet.type = 'text/css'; | |
document.getElementsByTagName('head')[0].appendChild(stylesheet); | |
// just use the native browser cache | |
// this requires a good expires header on the server | |
document.cookie = "font_css_cache"; | |
// if this isn't an old browser | |
} else { | |
// use the cached version if we already have it | |
if (fileIsCached(css_href)) { | |
injectRawStyle(localStorage.font_css_cache); | |
// otherwise, load it with ajax | |
} else { | |
var xhr = new XMLHttpRequest(); | |
xhr.open("GET", css_href, true); | |
// cater for IE8 which does not support addEventListener or attachEvent on XMLHttpRequest | |
xhr.onreadystatechange = function () { | |
if (xhr.readyState === 4) { | |
// once we have the content, quickly inject the css rules | |
injectRawStyle(xhr.responseText); | |
// and cache the text content for further use | |
// notice that this overwrites anything that might have already been previously cached | |
localStorage.font_css_cache = xhr.responseText; | |
localStorage.font_css_cache_file = css_href; | |
} | |
}; | |
xhr.send(); | |
} | |
} | |
} | |
// this is the simple utitily that injects the cached or loaded css text | |
function injectRawStyle(text) { | |
var style = document.createElement('style'); | |
// cater for IE8 which doesn't support style.innerHTML | |
style.setAttribute("type", "text/css"); | |
if (style.styleSheet) { | |
style.styleSheet.cssText = text; | |
} else { | |
style.innerHTML = text; | |
} | |
document.getElementsByTagName('head')[0].appendChild(style); | |
} | |
}()); | |
</script> |
I've done another update to prevent IE8 crashing. Moved the document.getElementsByTagName('head')[0].appendChild(style);
above the style.styleSheet.cssText = text;
@iamdarrenhall + @adamhavel: which is pretty weird, when you think about it. after all, it was IE who introduced us to innerHTML.
cu, w0lf.
Is there a way to do the same with just font files without combining them into a base encoded CSS file? Some web-font providers unfortunately don't allow to do that even if you're self hosting.
Take a look at my version, which is much more versatile: https://github.com/kurtextrem/localFont/blob/gh-pages/launcher.html
(I'd recommend to use a conditional for IE8 instead of loading it through the script though)
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
I've added a check to see if the XMLHTTPRequest response status code is 200, as it was caching a 404 page when the CSS file didn't get deployed.
Forked, updated and tested:
https://gist.github.com/iamdarrenhall/53b5eea54ac4bc25d0a6
Or just change line 54 to: