Skip to content

Instantly share code, notes, and snippets.

@branneman
Created May 3, 2016 08:39
Show Gist options
  • Save branneman/4eb5f5a9ae03901a52bef18c7a14818a to your computer and use it in GitHub Desktop.
Save branneman/4eb5f5a9ae03901a52bef18c7a14818a to your computer and use it in GitHub Desktop.
Asynchronously load fonts and cache them into localStorage
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Asynchronously load fonts and cache them into localStorage</title>
<script>
(function(d, w){
if (!('querySelector' in d && 'addEventListener' in window)) return;
d.documentElement.className = d.documentElement.className.replace('no-js', 'has-js');
d.addEventListener('DOMContentLoaded', function() {
// 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 = '/static/css/webfonts.css';
// if we have the fonts in localStorage or if we've cached them using the native batrowser cache
if ((w.localStorage && localStorage.font_css_cache) || d.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.
w.addEventListener("load", injectFontsStylesheet);
}
// quick way to determine whether a css file has been cached locally
function fileIsCached(href) {
return w.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 (!w.localStorage || !w.XMLHttpRequest) {
var stylesheet = d.createElement('link');
stylesheet.href = css_href;
stylesheet.rel = 'stylesheet';
stylesheet.type = 'text/css';
d.getElementsByTagName('head')[0].appendChild(stylesheet);
// just use the native browser cache
// this requires a good expires header on the server
d.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 = d.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;
}
d.getElementsByTagName('head')[0].appendChild(style);
d.documentElement.className += ' has-fonts-loaded';
}
});
}(document, window));
</script>
</head>
<body>
<h1 style="font-family:'univers-55-roman',arial,sans-serif">
I should be rendered in a custom font!
</h1>
</body>
</html>
@font-face {
font-family: 'univers-55-roman';
src: url('/static/fonts/univers-55-roman.eot');
src: url('/static/fonts/univers-55-roman.woff') format('woff'),
url('/static/fonts/univers-55-roman.ttf') format('truetype'),
url('/static/fonts/univers-55-roman.svg') format('svg');
font-weight: normal;
font-style: normal;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment