HomeDHTML & CSS
Creating an off-canvas side menu using CSS3 (and a touch of JavaScript)

Menu

Categories:AllFree JS/ AppletsTutorialsReferences

Creating an off-canvas side menu using CSS3 (and a touch of JavaScript)

Created: May 7th, 15

One of the most iconic menu patterns of the mobile era must be the
off-canvas side menu, which slides in from the edge of the window and
displaces the rest of the page horizontally when opened. By sidelining the
rest of the page, it focuses the user's attention squarely on the menu
itself, creating a user interface that's intuitive to use regardless of
device size. In this tutorial, we'll see how to create an off-canvas side
menu from scratch using CSS3 only, and with the help of a little JavaScript,
polish it off so it's fully ready for real world use.

Demo: Click on the "drawer" icon at the upper left corner of
this page.

The big idea

Lets first lay down the blueprint for how our off-canvas menu will be
created. The main steps are:

Surround our entire BODY content with a relatively positioned DIV to
easily shift it horizontally when the side menu is shown.

When the menu is opened, we'll shift both of the DIVs above to the right
using CSS3's "transform: translate3d()" property for silky smooth
transitioning.

Here's the secret diagram of how our menu will fit into an existing page:

Screenshot

The diagram doesn't include three other components involved in the making
of our off-canvas menu- a hidden checkbox and corresponding label element to
toggle the menu state, plus a semi opaque DIV that masks the rest of the
page while the menu is open. We'll cover them at the
right time in our tutorial.

Let the fun begin!

Lets take this from the very top- starting with a basic page with some dummy
content in it. Step by step we'll see how to integrate an off-canvas menu
into it:

Step 1: Wrapping the BODY content with a relatively positioned DIV

The first step is to wrap our entire BODY contents with a DIV that's
relatively positioned to easily shift the contents horizontally when the
menu is opened. Here is the CSS and markup for this wrapper DIV:

This DIV should surround your existing BODY content in their entirety. In the CSS above and to follow, we've omitted the vendor prefixed
versions of CSS3 related properties such as "transform" and "transition" for
brevity, though they should be present in the actual code. Turning our
attention to the CSS for the #contentarea DIV, we use "transform: translate3d(0,0,0);"
to prepare the element for shifting. where a value of "transform: translate3d(250px,0,0);"
for example would shift the element 250px to the right. Using the
"transform" property instead of CSS's "left" property has the advantage of
activating
3D hardware acceleration for smoother transitions. We also use the
"transition" property to indicate we wish to transition the "transform"
property when the property changes over 0.5 seconds.

Step 2: Defining the basic off-canvas menu

For the next step, lets create the canvas menu skeleton first without the
menu contents inside:

Notice the location of the off canvas menu element (#offcanvas-menu)
relative to the content wrapper (#contentarea)- it should be added outside
and above it, so the two elements are siblings.

To position the #offcanvas-menu element, well, off canvas, we set the
menu's position to "fixed" first, then utilize the CSS3 property transform:
"translate3d(-250px,0,0);"
to move the menu leftwards the length of the menu width.

Using visibility:hidden for browsers
that don't support CSS3's translate3d() value

Inside the #offcanvas-menu element, we've added
visibility:hidden for the sake of browsers that don't support CSS3's
translate3d(),
namely, IE9 and below, for offsetting and hiding the menu initially. Adding
this property however makes CSS3 transitions a bit more tricky. What we want
is our menu element to be visible immediately when it's transitioning from
being closed to open, so the other properties being transitioned are
visible to the user during this time. However for the reverse of
transitioning from being open to closed, we want our menu element to
stay visible until the other properties being transitioned have finished; in
other words, we want to set a delay before visibility:hidden is
applied in that case. To accomplish the two different behaviours depending
on the direction of the transition, initially, we have the following
values inside the transition property:

Here we are specifying that the transform property should
transition over 0.5 seconds, while for the visibility property,
it should complete immediately with no transitioning, but only after a delay
of 0.5 seconds (the second numeric value specifies the delay). Such a
setting takes care of the delay we need when the menu goes from being
open to closed- we want a 0.5s delay before the menu is hidden, the time
it takes for the other properties being transitioned to complete. Now, this
still leaves the other part of the visibility behaviour incomplete, which is
for the visibility property to have no delay when being applied whenever the
menu is being transitioned from closed to open.
We will implement that later.

Note: A good read on the subject of CSS3 transitions involving the
visibility property can be
found here.

Step 3: Adding a checkbox/label combo to toggle the menu

So far we have a blank off-canvas menu that's positioned outside the
browser's edge and invisible to the user. How do we go about revealing it?
An elegant, CSS only technique is to define a checkbox and LABEL(s) element
combo, then use the checkbox sibling technique to control the state
of sibling elements depending on the state of the checkbox itself, in this
case, the state of the "#offcanvas-menu" and "#contentarea" elements. If all
this sounds a bit overwhelming, fear not, we'll break everything down to bit
size morsels below.

Before anything else, first, we'll define a hidden checkbox and accompany
LABEL element to toggle the checkbox state. The checkbox should be added as
a sibling of the "#offcanvas-menu" and "#contentarea" element, and
proceeding them (we'll explain why very shortly). The LABEL element on the
other hand can be added anywhere your heart desires, in this case, our heart
says inside the "#contentarea" element:

Once again, the location of the checkbox element is very important- it should be
added above the off canvas menu and #contentarea DIV and
as a sibling of the later two. This is to facilitate the checkbox sibling
technique that we'll implement next to control the state of both the menu
and #contentarea
DIV based on the checked state of the checkbox itself. The location of the
LABEL element can be arbitrary.

Since the checkbox element is hidden (for aesthetics), we define a
corresponding label element to control the checkbox by setting the label's
"for" attribute to the ID of the checkbox. The style of the label element
creates the popular drawer look using a combination of border and CSS pseudo
element.

Lets get a snapshot of what our page looks like so far before continuing:

Step 4: Using the checkbox sibling technique to control the state of
sibling elements

Time to install the motor of our off-canvas menu, a mechanism to
open/close it plus displace the rest of the content on demand. The CSS only
technique basically centers around styling the desired siblings of a
checkbox that follow it when it's checked using the sibling selector (~), for
example:

The selector #togglebox:checked selects the #togglebox checkbox when it's
checked, while all together we are saying: "select the "#contentarea" sibling
DIV that follows the checkbox (not proceed it) when the former is checked."
The sibling selector (~) of CSS is only capable of selecting
siblings of an element that comes after it, which is why the order and
hierarchy of the 3 players - the checkbox, the menu and the "#contentarea" DIV
here- are so important.

Armed with the ability to style the menu and "#contentarea"
DIV differently based on whether the proceeding checkbox is checked or not,
all we have to do is style these elements so the menu is expanded and the "#contentarea"
shifted to the right by the amount of the menu width when the checkbox is
checked. Lets see how this looks in practice:

Selecting and styling the siblings of the #togglebox checkbox when
it's checked

Click on the drawer label now- viola, the off-canvas menu now slides into
view while nudging aside the rest of the content. When we click on the label
again, in turn unchecking it, we undo the styles defined for the two
elements, thus closing the menu again.

Continuing with the discussion
of using and transitioning the "visibility" property for the
sake of browsers that don't support CSS3's translate3d(), here
for the #offcanvas-menu's open state, we've set the element's "visibility"
to "visible" plus define the transition delay to 0s, or no
delay. Recall the reason for this- when the menu is transitioning from being
closed to open, what we want is the "visibility"
property to be applied immediately so the transitioning of the other
properties are visible to the user. Contrast that with when the menu is
transitioning from open to closed- in that case we want a delay of
0.5s - the transition time of the other properties, so the transition
effects are visible until the very end before hiding the menu.

We now know all the basic parts that go into creating an off-canvas menu.
On the next page, lets focus on refinement, by adding and stylizing the
content inside the menu and applying an overlay to the page when the menu is
open. Lets go!

Creating an off-canvas side menu using CSS3 (and a touch of JavaScript)