Test HTTP Requests Tools Blog Learn Quizzes Smile API Log In / Sign Up
Test HTTP Requests Tools Blog Learn Quizzes Smile API Log In / Sign Up
« Return to the tutorials list
We have updated the website and our policies to make sure your privacy rights and security are respected.
Click here to learn more about the way our website handles your data.

Remove this message.

The off-canvas navigation transitions from Codrops.com rewritten with jQuery

Daniel Gheorghe Difficulty: 50 / 50 Tweet

A few days ago a client asked me to reproduce the off canvas navigation and 3D Rotate Out effect shown here on their brand new website. Of course, I couldn't just copy and paste the code from the guys at Codrops because of the specifics of the project so I decided to rewrite it using jQuery and I am now sharing it with you guys.

Let's dive straight into the code.

<div id="codepunker-container" class="codepunker-container codepunker-effect-8">
  <div class="codepunker-pusher">
    <nav class="codepunker-menu codepunker-effect-8" id="menu-8">
      <h2>The Cool Menu</h2>
        <li><a href="#">Something</a></li>
        <li><a href="#">Something Else</a></li>
    <div class="codepunker-content">
      <div class="codepunker-content-inner">
        <header class="codrops-header">
          <h1>Sidebar Transitions <span>Transition effects for off-canvas views - Translated to jQuery by The CodePunker</span></h1>
        <div class="main clearfix">
          <div id="codepunker-trigger-effects" class="column">
            <button class="codepunker-toggler" data-effect="codepunker-effect-8">Bring it on</button>

The HTML above is almost the same as the one on I am referencing. It has a very basic structure - a container that wraps the sidebar navigation and the actual, visible website content. What we want to achieve is to show the sidebar using a cool effect, when the user clicks on the "Bring it on" button. Now let's have a look at the CSS.

.codepunker-container, .codepunker-pusher, .codepunker-content { 
  height: 100%; 
.codepunker-content { 
  overflow-y: scroll; background: #f3efe0; 
.codepunker-content, .codepunker-content-inner { 
  position: relative; 
.codepunker-container { 
  position: relative; overflow: hidden; 
.codepunker-pusher { 
  position: relative; left: 0; z-index: 1048; height: 100%; -webkit-transition: -webkit-transform 0.5s; transition: transform 0.5s; 
.codepunker-pusher::after { 
  position: absolute; top: 0; right: 0; width: 0; height: 0; background: rgba(63, 63, 67, 0.9); content: ''; opacity: 0; -webkit-transition: opacity 0.5s, width 0.1s 0.5s, height 0.1s 0.5s; transition: opacity 0.5s, width 0.1s 0.5s, height 0.1s 0.5s; 
.codepunker-menu-open .codepunker-pusher::after { 
  width: 100%; height: 100%; opacity: 1; -webkit-transition: opacity 0.5s; transition: opacity 0.5s; 
.codepunker-menu { 
  position: absolute; top: 0; left: 0; border-top: 1px solid #ebedef; z-index: 100; visibility: hidden; width: 300px; height: 100%; background: #2f2f33; -webkit-transition: all 0.5s; transition: all 0.5s; 
.codepunker-menu::after { 
  position: absolute; top: 0; right: 0; width: 100%; height: 100%; background: rgba(0, 0, 0, 0.2); content: ''; opacity: 1; -webkit-transition: opacity 0.5s; transition: opacity 0.5s; 
.codepunker-menu-open .codepunker-menu::after { 
  width: 0; height: 0; opacity: 0; -webkit-transition: opacity 0.5s, width 0.1s 0.5s, height 0.1s 0.5s; transition: opacity 0.5s, width 0.1s 0.5s, height 0.1s 0.5s; 
.codepunker-menu ul { 
  margin: 0; padding: 0; list-style: none; 
.codepunker-menu h2 { 
  margin: 0; padding: 1em; color: #434346; text-transform: uppercase; 
.codepunker-menu ul li a { 
  display: block; padding: 1em 1em 1em 1.2em; outline: none; box-shadow: inset 0 -1px rgba(0, 0, 0, 0.2); color: #f3efe0; text-transform: uppercase; text-shadow: 0 0 1px rgba(255, 255, 255, 0.1); letter-spacing: 1px; font-weight: 400; -webkit-transition: background 0.3s, box-shadow 0.3s; transition: background 0.3s, box-shadow 0.3s; 
.codepunker-menu ul li:fircodepunker-child a { 
  box-shadow: inset 0 -1px rgba(0, 0, 0, 0.2), inset 0 1px rgba(0, 0, 0, 0.2); 
.codepunker-menu ul li a:hover { 
  background: rgba(0, 0, 0, 0.2); box-shadow: inset 0 -1px rgba(0, 0, 0, 0); color: #fff; 

.codepunker-effect-8.codepunker-container { 
  -webkit-perspective: 1500px; perspective: 1500px; -webkit-perspective-origin: 0% 50%; perspective-origin: 0% 50%; 
.codepunker-effect-8 .codepunker-pusher { 
  -webkit-transform-style: preserve-3d; transform-style: preserve-3d; 
.codepunker-effect-8.codepunker-menu-open .codepunker-pusher { 
  -webkit-transform: translate3d(300px, 0, 0); transform: translate3d(300px, 0, 0); 
.codepunker-effect-8.codepunker-menu { 
  -webkit-transform: translate3d(-100%, 0, 0) rotateY(90deg); transform: translate3d(-100%, 0, 0) rotateY(90deg); -webkit-transform-origin: 100% 50%; transform-origin: 100% 50%; -webkit-transform-style: preserve-3d; transform-style: preserve-3d; 
.codepunker-effect-8.codepunker-menu-open .codepunker-effect-8.codepunker-menu { 
  visibility: visible; -webkit-transition: -webkit-transform 0.5s; transition: transform 0.5s; -webkit-transform: translate3d(-100%, 0, 0) rotateY(0deg); transform: translate3d(-100%, 0, 0) rotateY(0deg); 
.codepunker-effect-8.codepunker-menu::after { display: none; }
/* Fallback example for browsers that don't support 3D transforms (and no JS fallback) */
.no-csstransforms3d .codepunker-pusher, .no-js .codepunker-pusher { padding-left: 300px; }

The CSS 3 code is what creates all the cool animations through transitions and 3D transforms, which I will be explaining briefly below.

CSS 3 transitions are definitions of the animations that will happen when an element property is changed. For example, if an element has the transition property set to width 2s, if the element changes it's width, the change will occur gradually over a 2 seconds period.
CSS 3 transforms allow web developers to apply 2D or 3D transformations to HTML elements. Using the transform property you can rotate, skew, translate or scale HTML elements either in 2D or 3D.

The jQuery code is really simple - just a basic JavaScript class with two event triggers, properties for defining the container, the element triggering the animation and the types of events on which to trigger, depending on the type of device. The mobile check method will check the user agent of the browser against a set of common mobile device UA strings and is a replica of the detectmobilebrowsers.com JavaScript function.

var SidebarMenuEffects = function()

  this.mobilecheck = function()
    var check = false;
    (function(a){if(/(android|ipad|playbook|silk|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows (ce|phone)|xda|xiino/i.test(a)||/1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)|g1 u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp( i|ip)|hs\-c|ht(c(\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)|i230|iac( |\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc\-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|\-[a-w])|libw|lynx|m1\-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m\-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\-2|po(ck|rt|se)|prox|psio|pt\-g|qa\-a|qc(07|12|21|32|60|\-[2-7]|i\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\-|oo|p\-)|sdk\/|se(c(\-|0|1)|47|mc|nd|ri)|sgh\-|shar|sie(\-|m)|sk\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\-|v\-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\-|tdg\-|tel(i|m)|tim\-|t\-mo|to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas\-|your|zeto|zte\-/i.test(a.substr(0,4)))check = true;})(navigator.userAgent||navigator.vendor||window.opera);
    return check;

  this.container = jQuery( '#codepunker-container' );
  this.button = jQuery( '.codepunker-toggler' );
  this.eventtype = mobilecheck() ? 'touchstart' : 'click';

    targetClass = e.target.className;
    targetClass = targetClass.replace(" ", ".");
    allowed = (Boolean)( jQuery("." + targetClass).parents(".codepunker-menu").length > 0 || jQuery("." + targetClass).hasClass("codepunker-menu") );

  button.click(function(e) {
      effect = jQuery(this).attr('data-effect');
      container.attr("class", "codepunker-container");
      setTimeout( function() {
      }, 25 );

Here's a working demo of everything that you've learned in the tutorial. If you enjoyed it, go ahead and like my page on Facebook.