Managing JavaScript on Responsive Websites
The original breakout article on responsive web design came out in early 2010 (well, maybe it wasn't the first article, but it was certainly the one that moved responsive design firmly onto all our radars). Since then, responsive design has rocketed from a parlor trick only found on edgy portfolio sites to an accepted practice, finding its way into large-scale sites. For a sample of the breadth, variety and quality of sites using responsive design, check out mediaqueri.es.
On a recent responsive project, I quickly ran into a new challenge: how to manage JavaScript on a site where the interface and functionality changes at different breakpoints. For example, an image carousel might need to be animated at one breakpoint but turn into a simple image grid at the next; you don't want that JavaScript to still be functioning if someone crosses between them.
Foul!
Surely this kind of functionality isn't needed in the real world. Hasn't it been established that we're the only ones that resize our browsers to play with responsive sites while the rest of the world arrives on their phone, tablet or desktop machine and never realize that there's some magic under the hood to play with? I would argue that there's several legitimate cases for managing JavaScript as a page crosses between breakpoints:
- Initial page load: Even if the browser is never resized, breakpoint-specific JavaScript functions need to be fired accordingly.
- Development testing: Let's face it, browser resizing is one of the easiest ways that we test while building a site.
- Borderline device widths: Browser resizing and device rotation can cross breakpoints.
Looking for a solution
If your project only needs to support modern browsers, I highly recommend checking out Rob Tarr's mediaCheck which uses the new matchMedia method. But if you're using respond.js as a polyfill to ensure that your site responds on older browsers, some options are just starting to come onto the scene.
Enter jRespond
Since the project I was working on required browser support down to IE8 and I wanted my media queries and JavaScript to function (think older netbooks), I decided to create my own solution.
jRespond is a script that holds a list of user-defined functions that are fired based on the browser's width compared to a list of customizable breakpoints. Entry and exit functions can be defined so transitions between breakpoints can be managed by removing and unbinding some page elements while creating and binding others. jRespond was built to be independent and browser agnostic. It does NOT sniff for media queries in the stylesheets.
How does it work?
After including jRespond.js, call jRespond and define as many or as few media breakpoints as you need for your project. Labels can be any single-word string:
// call jRespond and add breakpoints
var jRes = jRespond([
{
label: 'handheld',
enter: 0,
exit: 767
},{
label: 'tablet',
enter: 768,
exit: 979
},{
label: 'laptop',
enter: 980,
exit: 1199
},{
label: 'desktop',
enter: 1200,
exit: 10000
}
]);
Once running, functions can be registered with jRespond along with a desired breakpoint:
// register enter and exit functions for a single breakpoint
jRes.addFunc({
breakpoint: 'desktop',
enter: function() {
myInitFunc();
},
exit: function() {
myUnInitFunc();
}
});
Or an array of breakpoints:
// register enter and exit functions for multiple breakpoints
jRes.addFunc({
breakpoint: ['desktop','laptop'],
enter: function() {
myInitFunc();
},
exit: function() {
myUnInitFunc();
}
});
The breakpoint parameter is required but the enter and exit parameters are optional (of course, at least one is required for something to happen).
Performance
jRespond is 1.3kb minified and only polls for the browser width every 500 milliseconds. If it detects a change the polling speed is increased to 100 milliseconds only until the browser width stops changing.
Compatible with: IE 6+, Safari 5+, Firefox 3+, Chrome 1+
Results
jRespond immediately became an invaluable part of the project that I was working on. It took the complex and messy task of managing each breakpoint-specific function independently and turned it into a quick and reliable process. Until matchMedia is more widely supported I plan on including jRespond in all my responsive projects.
Check it out over on GitHub.
So what do you think? Have you run into this problem yet? How did you solve it?