Off-Canvas Navigation

November 6, 2015

Keshia Brown

Keshia Brown

Earlier this week; I uploaded a short clip to Instagram, of an Off Canvas Navigation Menu that I had recently added to my website.

I had recently redesigned and developed my website (yup, again!) and was racking my brains over a concept for a new navigation menu. I wanted one that was a little fancy and at the same time, one that did not take anything away from a good user-experience and was also compatible on most devices and browsers. The previous navigation menus that have graced this space have been simple ‘click to reveal’ navigations that slid down and covered the whole page; they served their purpose and looked great but enough of that – enter the Off Canvas Navigation Menu.

Off Canvas Navigation menus are positioned outside of the view port and slide in when they are activated.

 

Structure

After revealing the initial off canvas navigation on Instagram, I continued to work on its structure; resulting in two more examples that appear from the right side (one that I will use for this tutorial) with an additional content-overlay that is activated when the menu appears. The HTML is pretty simple and is used in all three examples. I wrapped all of the navigation content inside of a header tag and then placed the div that holds the main content after it. The div that acts as the content-overlay is places just before the closing body tag.

<header id="navWrapper">
   <div class="menu-logo">
      <a href="http://keshiabrown.co.uk"><img src="http://keshiabrown.co.uk/blog/wp-content/themes/keshiabrown2/images/kblight.png" alt="logo"></a>
   </div>
   <div class="menuTrigger">
      <img src="example-open-nav" alt="navigation">
      <img src="expample-closing-nav" alt="navigation" style="display:none">
  </div> 

 <nav id="navMain">
    <div class="whiteBox">
       <div class="blackBox">
           <ul>
              <li><a href="http://keshiabrown.co.uk/about">About</a></li>
               <li><a href="http://keshiabrown.co.uk/projects">Projects</i></a></li>
                <li><a href="http://keshiabrown.co.uk/process">Process</i></a></li>
                <li><a href="http://keshiabrown.co.uk/contact">Contact</i></a></li>
                <li><a href="http://keshiabrown.co.uk/blog">Blog</i></a></li>
            </ul>
       </div>
    </div>
 </nav>

</header> 

<div class="main-content">
//Your content Here
</div>

<div class="container-fluid main-content-wrapper"></div>
     

 

– Menu Button

Just after the opening header tag, there’s a div that holds the menu buttons. I used two png images here, a hamburger button and an x-close button but you could easily swap this for glyph icons. The x-close png has an inline css style of ‘display: none’ which ensures that only the hamburger button is displayed until we swap it out with Jquery when it’s clicked.

– Off Canvas Wrap

Directly underneath the closing menu trigger div tag, I added a nav tag that serves as the menu wrapper for the off canvas navigation. Inside these tags, there’s a div for the first box that appears which has a class of ‘whiteBox‘ (I used the box colours so it was easier to follow) and inside the whitebox tags there’s another div called blackBox which of course is the second box to appear. Inside the blackBox div tags, I added an unordered list with links to my website pages and a span tag with social network icons (you don’t have to include this part).

– Main Content & Overlay

 After the closing header tag, I added a div that will hold all of the website content followed by a div that will act as the content overlay right before the closing body tag (remember to add the jquery script tag and a script tag for your own jquery file before closing body tag.

The CSS & Jquery

The css code for this off canvas navigation makes use of css3 transforms and transitions. Jquery is only used to handle the switching of the menu button pngs and the showing and hiding the off canvas navigation when the menu buttons are clicked by activating or deactivating the active classes set in css.

Body

Set body to position: relative as this establishes a new positioning context, the absolutely positioned descendant tags will be positioned with respect to the relatively positioned body edges instead of those of the window.

html, body {
    height: 100%;
    font-size: 100%;
}

body {
    color: #303030;
    font-family: sans-serif;
        position: relative;
    top: 0;
    margin: 0;
}


The Wrapper

The #navWrapper (header) is 50px high and absolutely positioned. This ensures that the nav scrolls with the page. I also added a high z-index (stack order) to ensure that the nav wrapper is always shown in front of the main content. You can also adjust the background-color to suit your needs.

#navWrapper {
    width: 100%;
    height: 50px;
    background-color: #303030;
    position: fixed;
    top: 0;
    z-index: 99999;
}


The Menu Trigger

The menu trigger div inside of the navWrapper div is absolutely positioned. The top and right properties may need adjusting if you opt for different pngs or glyphs.

.menuTrigger {
    position: absolute;
    top: 13px;
    right: 25px;
    z-index: 9999;
    cursor: pointer;
}

.menuTrigger img {
    height: 20px;
    max-width: 100%;
}


The Off Canvas Navigation Wrapper

Things get a little interesting with the introduction of the off canvas navigation wrapper (navMain div).

The background-color is the same as the navWrapper but this div has a fixed position. This ensures that the off canvas navigation stays right where it is on the screen if the user scrolls when it is activated.

I’ve set a height of 100vh, which is the same height as the viewport and a width of 260px to ensure that it remains responsive. The right value is set to -260px, with the negative value ensuring that the div is initially placed ‘off canvas.’

The interesting part is the introduction of the first transform and transition –

  • Transform allows you to manipulate an element by skewing, rotating, translating, or scaling.
  • Transitions allow you to change between property values smoothly (you’ll get this in just a moment)

For this element, I initially have transform: translate(0px, 0px) and transition: 0.75s ease, don’t forget to include vendor prefixes for different browsers (webkit, moz, o and ms!) – this ensures that before the nav button is clicked, the off canvas wrapper has not been moved neither right or left but when the nav button is clicked, it will ease out in 0.75s.

Following this, I have included an active class on the #navMain div (#navMain.active), this is activated with jquery (below) and adds a new class (.active)  to the div when the nav button is clicked(activated). The css for this element is transform: translate(-260px) – This moves the off canvas wrapper ‘back on canvas’ by changing the previous translate of 0 0 (o from right and 0 from left) to -260, (a negative value because our div originally has a right value of -260) this will bring it back to zero and it is now a div that is 260px wide (the width on the original element).

#navMain {
 background-color: #303030;
 position: fixed;
 right: -260px;
 width: 260px;
 top: 0px;
 height: 100vh;
 -webkit-transform: translate(0px, 0px);
 -moz-transform: translate(0px, 0px);
 -o-transform: translate(0px, 0px);
 -ms-transform: translate(0px, 0px);
 transform: translate(0px, 0px);
 -webkit-transition: 0.75s ease;
 -moz-transition: 0.75s ease;
 -o-transition: 0.75s ease;
 transition: 0.75s ease;
}

#navMain.active {
 -webkit-transform: translate(-260px);
 -moz-transform: translate(-260px);
 -o-transform: translate(-260px);
 -ms-transform: translate(-260px);
 transform: translate(-260px);
}


The White Box

The white box, black box and unordered list elements also take advantage of having an active class, both transitioning their height and widths with ease –  this creates a curtain reveal effect. The transform on these elements, paired with the absolute positioning, top, left and margin values ensures that the white box is centered within the nav wrapper and the black box is centered within the white box and the unordered list… yep you guessed right – CENTERED.

.whiteBox {
 height: 0;
 width: 0;
 background-color: #fff;
 right: 0;
 margin: 0 auto;
 position: absolute;
 top: 50%;
 left: 50%;
 transform: translate(-50%, -50%);
}

.whiteBox.active {
 height: 75vh;
 width: 230px;
 -webkit-transition: height 1s, width 1s ease 0s;
 -moz-transition: height 1s, width 1s ease 0s;
 -o-transition: height 1s, width 1s ease 0s;
 transition: height 1s, width 1s ease 0s;
}
.blackBox {
 height: 0;
 width: 0;
 background-color: #303030;
 position: absolute;
 top: 50%;
 left: 50%;
 -webkit-transform: translate(-50%, -50%);
 -moz-transform: translate(-50%, -50%);
 -o-transform: translate(-50%, -50%);
 -ms-transform: translate(-50%, -50%);
 transform: translate(-50%, -50%);
}

.blackBox.active {
 height: 72vh;
 width: 210px;
 -webkit-transition: width 0.5s ease 0.7s;
 -moz-transition: width 0.5s ease 0.7s;
 -o-transition: width 0.5s ease 0.7s;
 transition: width 0.5s ease 0.7s;
}
.blackBox ul {
    padding: 0;
    text-align: center;
    list-style-type: none;
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    margin: 0 auto;
}

.blackBox ul li {
    visibility: hidden;
    padding: 5px 0;
}

.blackBox ul li.active {
    visibility: visible;
    -webkit-transition: visibility 2s ease 1.23s;
    -moz-transition: visibility 2s ease 1.23s;
    -o-transition: visibility 2s ease 1.23s;
    transition: visibility 2s ease 1.23s;
}

.blackBox ul li a {
    display: inline-block;
    padding: 10px 25px;
    font-family: monospace;
    text-transform: uppercase;
    font-size: 1.65em;
    position: relative;
    color: #fff;
}

.blackBox ul li a:hover {
    background-color: #fff;
    color: #303030;
    -webkit-transition: all 0.3s ease 0s;
    -moz-transition: all 0.3s ease 0s;
    -o-transition: all 0.3s ease 0s;
    transition: all 0.3s ease 0s;
}

The Main Content

The CSS for the main page content also has an active class. This pushes the main content to the right by 260px (-260px) when the off canvas navigation is activated and moves it back when it’s deactivated – all with an ease of 0.75s.

.main-content {
 position: relative;
 top: 0;
 background-color: #fff;
 width: 100%;
 padding: 75px 0 0 0;
 -webkit-transform: translate(0px);
 -moz-transform: translate(0px);
 -o-transform: translate(0px);
 -ms-transform: translate(0px);
 transform: translate(0px);
 -webkit-transition: 0.75s ease;
 -moz-transition: 0.75s ease;
 -o-transition: 0.75s ease;
 transition: 0.75s ease;
}

.main-content.active {
 -webkit-transform: translate(-260px);
 -moz-transform: translate(-260px);
 -o-transform: translate(-260px);
 -ms-transform: translate(-260px);
 transform: translate(-260px);
}

The Content Overlay

The content overlay uses an active class to create an overlay that dims out the main content when the off canvas navigation is activated. The transition of the active class toggles between the opacity of the original overlay div.

.content-overlay {
    z-index: 4000;
    position: absolute;
    position: fixed;
    display: block;
    content: "";
    top: 0;
    left: 0%;
    width: 100%;
    height: 0;
    opacity: 0;
    background: rgba(73,75,76,0.7);
    -webkit-transition: opacity 300ms ease,height 1ms 300ms ease;
    transition: opacity 300ms ease,height 1ms 300ms ease;
    -webkit-transform: translate3d(0, 0, 0);
    transform: translate3d(0, 0, 0);
    -webkit-backface-visibility: hidden;
    backface-visibility: hidden;
}

.content-overlay.active {
    height: 100%;
    opacity: 1;
    -webkit-transition: opacity 300ms ease;
    transition: opacity 300ms ease;
}

And finally, the Jquery

The Jquery is basic and consists of 10 lines. The code activates the active classes shown in the css code above when the menu trigger button is clicked. It also swaps the menu buttons when clicked.

jQuery(document).ready(function($){
    //when the menu trigger button is clicked
    $('.menuTrigger').click(function() {

        //Toggle acitve classes on divs and span
        $('.content-overlay').toggleClass("active");
        $('#navMain').toggleClass("active");
        $('.whiteBox').toggleClass("active");
        $('.blackBox').toggleClass("active");
        $('.blackBox ul li').toggleClass("active");
        $('.socialBtns').toggleClass("active");
        $('.main-content').toggleClass("active");

        //Find img tags within the div and toggle them
        $(this).find('img').toggle();
    });
    
});

You can find demo’s for all three navigations HEREfeel free to experiment with the files, maybe even using 3d transforms!

Leave a Reply

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