Cloud Four Blog

Technical notes, War stories and anecdotes

Our Off-Canvas Menu Plugin

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.

Flexibility

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.

Performance

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.

20 Comments on “Our Off-Canvas Menu Plugin”

  1. Lyza Gardner says:

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

  2. JF says:

    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 !

    • Matt Gifford says:

      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.

    • nzj says:

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

  3. DFX says:

    Hi!, great work, only problem is that links stop working in Android and i don’t have a clue how to fix that :(

  4. Paul Frost says:

    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?

    • Matt Gifford says:

      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.

  5. Ad says:

    Was just trying this out to see what its like with hammer.js but having an issue calling it in. Put it on stackoverflow if anyone knows how to do it properly

    http://stackoverflow.com/questions/17176594/hammer-js-swipe-in-an-off-canvas-element

    Great plugin though!

  6. Dave says:

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

    • Matt Gifford says:

      No. But you’re not the first to ask about it. I’m starting to think we should do it.

  7. 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.

    • Matt Gifford says:

      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.

  8. Laurelle says:

    Hi,

    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.

    • Tyler Sticka says:

      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.

  9. Laurelle says:

    Thank you, that was the help that I needed.

  10. Pedro says:

    Hi!
    It is possible to have two OffCanvasMenu’s in the same page? One in left side and another in the right side?

  11. Flynn says:

    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.