JS 201: Run a function when a stylesheet finishes loading
Published on .This post originally appeared on Viget’s Inspire blog.
This is the first in a series I’m calling, “JS 201.” It’s not introductory material, but is instead that helpful middle ground between the basics and pretty much anything John Resig writes. Short, practical, typically plain-ol’-JavaScript tips is what you’ll get.
I’m in the middle of working out a new feature for a project that requires JavaScript to append some markup, stylesheets, and scripts to a page. The task is fairly straightforward: JavaScript has native capability to do all of that. I’m looking at you, createElement
and appendChild
.
I did run into a problem, though. A piece of JavaScript required styles be applied to certain elements before it should execute. Unfortunately, the script was executing while the stylesheet was being loaded. Like most reasonable front-end developers, I figured I’d just run a function when the onload
event fired on the link
element. It works for images, why not for stylesheets, right? Wrong!
Currently, only Opera and Internet Explorer support the onload
event and onreadystatechange
respectively. Strange bedfellows, for sure, but that leaves us with the entire Gecko and WebKit landscape without anything approximating the onload
event.
What are we to do? Exploit the img
element’s onerror
event, that’s what!
var head = document.getElementsByTagName( "head" )[0],
body = document.body,
css = document.createElement( "link" ),
img = document.createElement( "img" ),
cssUrl = "/path/to/a/css/file.css";
css.href = cssUrl;
css.rel = "stylesheet";
head.appendChild( css );
img.onerror = function() {
// Code to execute when the stylesheet is loaded
body.removeChild( img );
}
body.appendChild( img );
img.src = cssUrl;
What’s happening above isn’t at all complex. We first grab references to the head
and body
. We create our link
and a dummy img
and define the path to our CSS file. Next, we set some attributes on our link
element and append it to the head
.
The next few lines are the sneaky bits. We first set a function on the img
to run when its onerror
event fires. This is where we put our code that we want to execute after the stylesheet is loaded. After that, we append the img
to the body
and then set its source to our CSS file path. The order of operations there is important, so don’t swap those lines!
What happens behind the scenes is that the browser tries to load the CSS in the img
element and, because a stylesheet is not a type of image, the img
element throws the onerror
event and executes our function. Thankfully, browsers load the entire CSS file before determining its not an image and firing the onerror
event.
It’s far from pretty, but it works, and it doesn’t take a lot of extra code to make happen.
For further reading (and for some different examples), check out the following posts that served as reference and inspiration for this article: