Our Off-Canvas Menu Plugin

Written by Matt Gifford on

On a recent responsive design project, we wanted an off-canvas menu for narrow viewports. We tried some of the off-canvas menu libraries out there. But, being very particular about design and performance, we ended up writing our own.

Our library, the not-so-creatively-named offCanvasMenu, is a jQuery/Zepto plugin built for flexibility and performance.


Many of the libraries we tried required that we structure our HTML in a certain way. Others were built to be a complete responsive menu solution, having their own opinions about where the breakpoints should be. We found both of these aspects to be too restrictive.

offCanvasMenu doesn’t depend on the structure of your HTML. Just specify which elements to use for the menu and menu trigger, and the plugin takes care of the rest.

It is not a responsive menu. It’s meant to be used as part of the responsive system you’re already using. Your code determines when to turn it on and off. The plugin also exposes methods for opening and closing the menu, if you wish to add support for other gestures, such as swipe.


offCanvasMenu, when used with Modernizr, will use CSS transforms for animation if the browser supports it. Of course, if the browser doesn’t support CSS transforms, it will fall back to using jQuery/Zepto animation.

It also eliminates the 300 ms delay between a tap and the resulting animation by firing on touchstart and mousedown, rather than click.

Update: We’ve changed our thinking on tap-handling within the plugin and have removed the feature. This is best handled on the page level, using a library like FastClick.

Try It Out

You can see the plugin in action as part of a responsive design on its GitHub page. To see more examples or get the plugin, go to the repository page. Please let us know if you have suggestions for improvement or run into any problems.

We hope you find it useful.


Woot! Glad to see this get out there. Nice illustration of some thoughtful techniques and separation of concerns. Yay, team!

Great Job, good concepts !

Just too bad it doesn't play well with multiple instance on the same page, but I'll probably adapt it so it can.

Thanks for sharing !


JF, we talked about adding that late in development, but didn't get around to it. If you add that functionality, please send us a pull request.

I'm interested to use it for multiple instance on the same page too! Would love to see your adaptation.

You mention it's possible to add support for other gestures, such as swipe.
I really like the method you are using, but I'm thinking of using it with a very long list of navigation options in the menu, which on a phone would be longer than one screenful. I thought it would be nice to have the option to swipe the menu off screen if you had scrolled down and the menu button was no longer visible.
I've had a look around the code and on the jQuery website to see if I could solve it myself but my javascript is not up to the task. Can you point me in the right direction or supply an example?

Paul Frost


The easiest way to do this would be to add a JS library that can detect swipes, such as hammer.js or swipe.js. Once you're able to detect swipes, it's just a matter of calling the menu's show or hide methods, depending on which direction the swipe is going.

Cool does this support 2 menus ie one on left and right?

Any performance tuning for large pages? Do css transforms have a threshold on large pages with lots of content or does the gpu handle the movement in almost every case? Looking at a project where more than a menu is hidden and large pages would be hidden when the new "menu/page" animates in.

Josh McKenney


I'm not aware of it having been used on large pages yet. It's fairly easy to implement. My suggestion would be to try it both with and without Modernizr to see how it performs.


Is there a way to stop the mobile menu from displaying when you first load the page? It displays for about a second and then disappears. I would like to not have the mobile menu display when the page first loads.

Thank you.


The menu will not receive any custom styles until the plugin has had a chance to activate. With this in mind, there are a few ways you might prevent it from displaying initially.

The simplest way would be to hide the menu by default using CSS:

.my-menu { display: none; }

...then show it again when the plugin is active:

.off-canvas-menu .my-menu { display: block; }

You could also try reducing the time the JavaScript takes to activate by moving it higher in your source. This may slow down the overall experience, though.

If nothing's working, you should totally open a GitHub issue with more detail.

Thank you for sharing this menu! I tried other plugins, but their code was bloated with too many bells and whistles. I love the fact that your code is simple, lightweight and flexible.

Let’s discuss your project! Email Us