Known as off canvas menus, shelf menus, or panels, they are commonly seen in apps, but they are getting popular in responsive desktop sites as well.

There have been a lot of articles written on this, but I wanted to make a really simple, understandable version. This is basically a simple version of David Bushell’s off canvas menu. I used a similar menu in the m1 WordPress theme.

With a little bit of CSS and jQuery magic we can turn our regular nav menu into a shelf menu at smaller screen widths.

View demo (Make browser smaller if necessary)

Pretty cool, right? And not very difficult!

Let’s talk this through

What’s basically happening is that the menu is being moved off the screen to the left at smaller browser widths.

When the menu button is clicked, the entire thing (menu and page) is moved to the right to reveal the menu. Here’s the sequence (yellow box is the browser viewport):

Off Canvas Navigation Menu

Let’s take a look at some code:

See the Pen Simple Responsive Off Canvas Navigation Menu by Scott Bolinger (@scottb) on CodePen

HTML: Nothing fancy here, but do take note where each element is in the structure, it is important. A #page div wraps everything, then the open button, then the nav with the close button and menu inside.

CSS: Media queries are moving the menu off the screen using absolute positioning, and stacking it vertically.

jQuery: We are just adding/removing a class on the buttons that open/close the menu. Super simple!

Transitions: We could do the transitions with jQuery using .animate(), but we pay a huge performance penalty. Instead, we’ll use CSS transitions, specifically translate3d. Using translate3d allows us to use hardware acceleration, a huge bonus.

The CSS

Lines 1-45 are just setting things up, displaying the normal menu and hiding the open/close buttons.

It gets more interesting in the media query on line 47. First we are moving the nav off screen with absolute positioning, combined with some transform values. The transform values are setting up the menu for our panel open/close animations later. (I’m going to use unprefixed properties to simplify things visually)

nav {
    width: 70%; /* The menu should only take up 70% of the screen when open */
    position: absolute;
    left: 0;
    top: 0;
    height: 100%; /* Make sure to take up the whole screen height, it looks better */
    background: #777;
    transform: translate3d(-100%, 0, 0); /* Move the menu all the way off the screen */
}

Lines 65-87 are displaying the menu vertically, and showing the open/close buttons. Not much to see there.

Transitions

The magic starts on line 90, where we are adding the open/close transitions. Our jQuery is adding the class of .openNav to our html tag when the .open-panel button is clicked, using .addClass():

$(".open-panel").click(function(){
  $("html").addClass("openNav");
});

The CSS for opening the panel can then use the .openNav class:

/* Slide entire page over, revealing nav when open button clicked */
.openNav #page {
    left: 0;
    transform: translate3d(70%, 0, 0);
    transition: transform 500ms ease;
}

Once our html tag gets the class of .openNav via jQuery, the page slides to the right 70%.

To close the panel, all we are doing is reversing the process. When the .close-panel button is clicked, we just remove the .openNav class from our html tag.

$(".close-panel, #content").click(function(){
  $("html").removeClass("openNav");
});

You’ll notice I also added #content to the mix, that makes it so if you click the body of the page content it also closes the panel. Optional, but a little nicer.

To make sure our page transitions nicely when closed, we add this to our CSS (again unprefixed):

/* When the panel is closed, transition the page back to the left */
#page {
    left: 0;
    transform: translate3d(0, 0, 0);
    transition: transform 500ms ease;
}

Browser Support & More

I made this menu as a simplified version to help you understand the fundamentals. Browser support adds a lot of complexity, so I left a lot of that out here.

This menu will work on most browsers, but probably not IE8 or below. Also, the animations are choppy in Firefox. If you need full browser support, I’d recommend using Modernizr and adding some fallbacks. David Bushell’s article has some great ideas on that.

If you are seeing a flicker on mobile devices, try adding -webkit-backface-visibility: hidden; to the elements with translate3d.

If you have any questions, leave them in the commments. Cheers!

5 thoughts on “Responsive Off Canvas Navigation Menu

  1. Hi Scott

    It is so refreshing to see a simple but equally effective implementation of the off canvass menu.

    I have implemented your menu but noticed that it does not work on IE9. I was wondering how you would accommodate this using the jquery?

  2. Thanky you Scott,

    It work’s great. But, what about if I want to use sticky header(fixed header)? It’ doesn’t scroll, is there a way to make fixed header scroll with this off-canvas example.

    Thank you once again.

Leave a Reply

Your email address will not be published. Required fields are marked *