How to lazy-load CSS with JavaScript
Posted on August 28, 2014 • 2 minutes • 363 words
Prioritize above the fold content and defer loading CSS can significantly improve your site’s rendering speed (impression, at the very least) and PageSpeed score. Basically, you will inline those CSS rules so that content above the fold (content visible without scrolling down) can be render right away (instead of getting blocked while waiting for the whole CSS file being downloaded), making visitors feel that the site is responsive.
You can use this bookmarklet
to identify the critical CSS rules. Note that this will not pickup the @media
query. That, you will have to do by yourself for now.
Once you’ve finished identifying those above-the-fold CSS rules and inline them, you will have to lazy-load the rest of the CSS with JavaScript.
If you’re using jQuery
, put this in your ready
block. Otherwise, write your own version of ready
and put it there
This is an example of ready
in pure JavaScript. I don’t need jQuery anywhere else on my site so including jQuery is too much overhead for this purpose.
(function(funcName, baseObj) {
funcName = funcName || "isReady";
baseObj = baseObj || window;
var readyList = [];
var readyFired = false;
var readyEventHandlersInstalled = false;
function ready() {
if (!readyFired) {
readyFired = true;
for (var i = 0; i < readyList.length; i++) {
readyList[i].fn.call(window, readyList[i].ctx);
}
readyList = [];
}
}
function readyStateChange() {
if ( document.readyState === "complete" ) {
ready();
}
}
baseObj[funcName] = function(callback, context) {
if (readyFired) {
setTimeout(function() {callback(context);}, 1);
return;
} else {
readyList.push({fn: callback, ctx: context});
}
if (document.readyState === "complete") {
setTimeout(ready, 1);
} else if (!readyEventHandlersInstalled) {
if (document.addEventListener) {
document.addEventListener("DOMContentLoaded", ready, false);
window.addEventListener("load", ready, false);
} else {
document.attachEvent("onreadystatechange", readyStateChange);
window.attachEvent("onload", ready);
}
readyEventHandlersInstalled = true;
}
}
})("isReady", window);
Function to lazy-load CSS
function loadCSS(href){
var ss = window.document.createElement('link'),
head = window.document.getElementsByTagName('head')[0];
ss.rel = 'stylesheet';
ss.href = href;
// temporarily, set media to something non-matching to ensure it'll
// fetch without blocking render
ss.media = 'only x';
head.appendChild(ss);
setTimeout( function(){
// set media back to `all` so that the stylesheet applies once it loads
ss.media = 'all';
},0);
}
Once ready, load the rest of the CSS
isReady(function() {
loadCSS('/assets/css/main.css');
});