Last active
May 1, 2019 06:10
-
-
Save rungta/fa39058f1d15d6d4ea95 to your computer and use it in GitHub Desktop.
Load CSS `@font-face` fonts by listening for font loading events. A workaround while we wait for browsers to support the `font-rendering: swap` property.
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
/** | |
* fontloader.js | |
Helps you avoid FOIT and progressively load in multiple | |
sets of webfonts as asynchronous non-blocking resources. | |
Apply them on the page when the fonts are ready, like so: | |
.title-type { font-family: serif; } | |
.prose-type { font-family: sans-serif; } | |
.webfonts-active .title-type { font-family: Noto Serif, serif; } | |
.webfonts-active .prose-type { font-family: Noto Sans, sans-serif; } | |
Why bother? | |
- https://miranj.in/blog/2015/collateral-damage | |
- https://www.filamentgroup.com/lab/js-web-fonts.html | |
* Created by Prateek Rungta | |
Copyright (c) 2015 Miranj Design LLP | |
* Font activation on load based on code from | |
http://www.filamentgroup.com/lab/font-events.html | |
Copyright (c) 2015 Filament Group | |
* Dependencies: | |
- FontFaceObserver https://github.com/bramstein/fontfaceobserver | |
**/ | |
(function (w) { | |
'use strict'; | |
var fontsets = [{ | |
fonts: { | |
'Noto Serif': [ | |
{ 'weight': 400 }, | |
{ 'weight': 400, 'style': 'italic' }, | |
{ 'weight': 700 } | |
], | |
'Noto Sans': [ | |
{ 'weight': 700 } | |
] | |
}, | |
activeClass: 'webfonts-active', | |
cacheKey: 'webfonts-cached', | |
}], | |
timeout = 5*60*1000; // give it 5 mins before timing out | |
// hasClass polyfill | |
// from http://youmightnotneedjquery.com/#has_class | |
function hasClass(el, className) { | |
if (el.classList) { | |
return el.classList.contains(className); | |
} | |
return new RegExp('(^| )' + className + '( |$)', 'gi').test(el.className); | |
} | |
function isSessionStorageSupported() { | |
try { | |
var mod = 'test'; | |
sessionStorage.setItem(mod, mod); | |
sessionStorage.removeItem(mod); | |
return true; | |
} catch(e) { | |
return false; | |
} | |
} | |
function loadFonts(fontsets) { | |
// get the first fontset | |
if (fontsets.length === 0) return; | |
var config = fontsets.shift(); | |
function activate() { | |
// add a class to the document indicating the fonts have loaded | |
w.document.documentElement.className += ' ' + config.activeClass; | |
// set a flag to optimise future visits | |
if (isSessionStorageSupported()) sessionStorage.setItem(config.cacheKey, true); | |
// recurse over remaining fontsets | |
loadFonts(fontsets); | |
// fire resize event to trigger dimension recalculations | |
if (window.jQuery) { jQuery(window).resize(); } | |
} | |
// if we do not have FontFaceObserver, Promise, or ECMAScript 5, activate & fail | |
if (!('FontFaceObserver' in w) || !('Promise' in w) || !('keys' in Object)) return activate(); | |
// if the class is already set, we're good. | |
if (hasClass(w.document.documentElement, config.activeClass)) return activate(); | |
// if the fonts are already cached by the browser, activate them | |
if (isSessionStorageSupported() && sessionStorage.getItem(config.cacheKey)) return activate(); | |
// loop over font list and create an observer for each weight | |
var observers = []; | |
Object.keys(config.fonts).forEach(function (fontFamily) { | |
config.fonts[fontFamily].forEach(function (fontProperties) { | |
var new_observer = new w.FontFaceObserver(fontFamily, fontProperties); | |
observers.push(new_observer.load(config.testString || null, timeout)); | |
}); | |
}); | |
w.Promise.all(observers).then(activate); | |
} | |
loadFonts(fontsets); | |
}(this)); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment