Add an Off-Canvas Menu to Your Genesis Child Theme

This tutorial is no longer maintained.

It may still be fully functional as-is; exercising caution is recommended.
Please be sure to test thoroughly.

I’m a huge fan of Codrops, and in particular the Collective; but that’s off-topic. For some time I’ve been playing with some of the inspirational elements and adjusting them to work in a Genesis child theme.

So, today I’m sharing one of my experiments – hope you enjoy!

Inspiration

See the original article of Off-Canvas Menu Effects at Codrops.

I’ll be recreating the Elastic version and inserting a new widget area so you can add a menu, search bar, etc if so desired.

The Functions

Let’s start with the meat of the project – functions.php.

<?php
/**
 * GENESIS OFF-CANVAS MENU
 * Adapted from Codrops - http://tympanus.net/codrops/2014/09/16/off-canvas-menu-effects/
 *
 * @author      Erica Franz @ericakfranz
 * @authoruri   https://jng.xdv.mybluehost.me/fatpony-new
 * @link        https://jng.xdv.mybluehost.me/fatpony-new/genesis-off-canvas-menu
 * @link        http://github.com/ericakfranz/genesis-off-canvas-menu
 *
 * @version     1.0
 *
 * @license     GNU General Public License v2 or later
 */
// Remember to enqueue your scripts!
add_action('wp_enqueue_scripts', 'fatpony_load_scripts');
// Load Elastic Sidebar scripts only if sidebar is active
// - no reason to waste resources
function fatpony_load_scripts()
  {
  if(is_active_sidebar('elastic-sidebar'))
    {
    wp_enqueue_script('snap-svg', get_stylesheet_directory_uri() . '/js/snap.svg-min.js', array(), null, false);
    // Load footer scripts
    wp_enqueue_script('classie', get_stylesheet_directory_uri() . '/js/classie.js', array(), null, true);
    wp_enqueue_script('elastic', get_stylesheet_directory_uri() . '/js/elastic.js', array(), null, true);
    }
  }
// Remove default header widget - untested with the header right widget intact
unregister_sidebar('header-right');
// Register new sidebar
genesis_register_sidebar(array(
  'id' => 'elastic-sidebar',
  'name' => __('Elastic Sidebar', 'theme_name'),
  'description' => __('This is the elastic sidebar area. Anything you place inside will be hidden until activated with the menu icon, then bounce into view using an elastic-like animation.', 'theme_name')
));
// Hook into header area
add_action('genesis_before', 'fatpony_elastic_sidebar');
function fatpony_elastic_sidebar()
  {
  genesis_widget_area('elastic-sidebar', array(
    'before' => '<div class="container">
             <div class="elastic-wrap">
             <div class="elastic-widget-wrap">',
    'after' => '</div>
             <button class="close-button" id="close-button">
                 <span class="assistive-text">Close Menu</span>
            </button>
             <div class="morph-shape" id="morph-shape" data-morph-open="M-1,0h101c0,0,0-1,0,395c0,404,0,405,0,405H-1V0z">
                 <svg xmlns="http://www.w3.org/2000/svg" width="100%" height="100%" viewBox="0 0 100 800" preserveAspectRatio="none">
                     <path d="M-1,0h101c0,0-97.833,153.603-97.833,396.167C2.167,627.579,100,800,100,800H-1V0z"/>
                 </svg>
             </div>
         </div>
         <button class="menu-button" id="open-button">
             <span class="assistive-text">Open Menu</span>
         </button>
         <div class="site-container-wrap">' 
    ));}
// Wrap up loose ends
add_action('genesis_after', 'fatpony_loose_ends');
function fatpony_loose_ends()
  { echo '</div></div>'; }
Code language: PHP (php)

Dependencies

Not jQuery dependent, but does use a couple of scripts to make it all happen including the snap.svg library. These also go in your functions.php file.

// Remember to enqueue your scripts!
add_action( 'wp_enqueue_scripts', 'fatpony_load_scripts' );

// Load Elastic Sidebar scripts only if sidebar is active
// - no reason to waste resources
function fatpony_load_scripts() {
	if( is_active_sidebar( 'elastic-sidebar' ) ) {
		wp_enqueue_script( 'snap-svg', get_stylesheet_directory_uri() . '/build/js/snap.svg-min.js', array(), null, false );
		// Load footer scripts
		wp_enqueue_script( 'classie', get_stylesheet_directory_uri() . '/build/js/classie.js', array(), null, true );
		wp_enqueue_script( 'elastic', get_stylesheet_directory_uri() . '/build/js/elastic.js', array(), null, true );
	}
}
Code language: PHP (php)

The CSS

I made some adjustments to the CSS in the Codrops demo, aside from what was needed to play nicely in Genesis. Some changes were to improve the potential of use on a live site, but use at your own discretion in the wild.

html, body, .container, .site-container-wrap {
     overflow: hidden;
     width: 100%;
     height: 100%;
}
 body {
     background-color: #000;
}
 .site-container-wrap {
     overflow-y: scroll;
     -webkit-overflow-scrolling: touch;
     -webkit-transition: -webkit-transform 0.3s;
     transition: transform 0.3s;
     background-color: #fff;
}
 .site-container {
     position: relative;
}
 .site-container::before {
     position: absolute;
     top: 0;
     left: 0;
     z-index: 10;
     width: 100%;
     height: 100%;
     background: rgba(0,0,0,0.3);
     content: '';
     opacity: 0;
     -webkit-transition: opacity 0.3s, -webkit-transform 0s 0.3s;
     transition: opacity 0.3s, transform 0s 0.3s;
     -webkit-transform: translate3d(100%,0,0);
     transform: translate3d(100%,0,0);
}
/* Menu Button */
 button.menu-button {
     position: fixed;
     z-index: 1000;
     margin: 0.25em;
     padding: 0;
     width: 2em;
     height: 1.85em;
     border: none;
     font-size: 1.5em;
     text-indent: 2.5em;
     color: transparent;
     background: transparent;
}
 button.menu-button::before {
     position: absolute;
     top: 0.5em;
     right: 0.5em;
     bottom: 0.5em;
     left: 0.5em;
    /* Updated gradients to make as cross-browser-friendly as possible */
     background: rgba(68,68,68,1);
     background: -moz-linear-gradient(top, rgba(68,68,68,1) 0%, rgba(68,68,68,1) 20%, rgba(255,255,255,1) 20%, rgba(255,255,255,1) 40%, rgba(102,102,102,1) 40%, rgba(102,102,102,1) 60%, rgba(255,255,255,1) 60%, rgba(255,255,255,1) 80%, rgba(136,136,136,1) 80%, rgba(136,136,136,1) 100%);
     background: -webkit-gradient(left top, left bottom, color-stop(0%, rgba(68,68,68,1)), color-stop(20%, rgba(68,68,68,1)), color-stop(20%, rgba(255,255,255,1)), color-stop(40%, rgba(255,255,255,1)), color-stop(40%, rgba(102,102,102,1)), color-stop(60%, rgba(102,102,102,1)), color-stop(60%, rgba(255,255,255,1)), color-stop(80%, rgba(255,255,255,1)), color-stop(80%, rgba(136,136,136,1)), color-stop(100%, rgba(136,136,136,1)));
     background: -webkit-linear-gradient(top, rgba(68,68,68,1) 0%, rgba(68,68,68,1) 20%, rgba(255,255,255,1) 20%, rgba(255,255,255,1) 40%, rgba(102,102,102,1) 40%, rgba(102,102,102,1) 60%, rgba(255,255,255,1) 60%, rgba(255,255,255,1) 80%, rgba(136,136,136,1) 80%, rgba(136,136,136,1) 100%);
     background: -o-linear-gradient(top, rgba(68,68,68,1) 0%, rgba(68,68,68,1) 20%, rgba(255,255,255,1) 20%, rgba(255,255,255,1) 40%, rgba(102,102,102,1) 40%, rgba(102,102,102,1) 60%, rgba(255,255,255,1) 60%, rgba(255,255,255,1) 80%, rgba(136,136,136,1) 80%, rgba(136,136,136,1) 100%);
     background: -ms-linear-gradient(top, rgba(68,68,68,1) 0%, rgba(68,68,68,1) 20%, rgba(255,255,255,1) 20%, rgba(255,255,255,1) 40%, rgba(102,102,102,1) 40%, rgba(102,102,102,1) 60%, rgba(255,255,255,1) 60%, rgba(255,255,255,1) 80%, rgba(136,136,136,1) 80%, rgba(136,136,136,1) 100%);
     background: linear-gradient(to bottom, rgba(68,68,68,1) 0%, rgba(68,68,68,1) 20%, rgba(255,255,255,1) 20%, rgba(255,255,255,1) 40%, rgba(102,102,102,1) 40%, rgba(102,102,102,1) 60%, rgba(255,255,255,1) 60%, rgba(255,255,255,1) 80%, rgba(136,136,136,1) 80%, rgba(136,136,136,1) 100%);
     filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#444444', endColorstr='#888888', GradientType=0 );
     content: '';
}
 button.menu-button::hover {
     opacity: 0.6;
}
/* Morph Shape */
 .morph-shape {
     position: absolute;
     height: 100%;
     width: 120px;
     top: 0;
     right: 0;
     fill: #222222;
     z-index: 1000;
}
/* Elastic Wrap */
 .elastic-wrap {
     position: absolute;
     z-index: 1001;
     width: 400px;
     height: 100%;
     font-size: 1.15em;
     -webkit-transform: translate3d(-400px,0,0);
     transform: translate3d(-400px,0,0);
     -webkit-transition: -webkit-transform 0.3s;
     transition: transform 0.3s;
     background-color: transparent;
}
 .elastic-wrap a {
     color: #dddddd;
     font-size: 0.8em;
     letter-spacing: 0.05em;
     line-height: 1em;
}
 .elastic-wrap a::hover {
     color: #ffffff;
     border-bottom: none;
     text-decoration: none;
}
/* Elastic Widgets */
 .elastic-widget-wrap {
     background-color: #222222;
     width: 100%;
     height: 100%;
     padding-right: 130px;
    /* Prevent the widgets from running over into the morph shape 
    /* 
}
/* Elastic Menu */
 .elastic-wrap .menu {
     height: 100%;
     overflow: hidden;
}
 .elastic-wrap .menu li {
     width: 380px;
}
 .elastic-wrap menu li a {
     display: block;
     padding: 0.8em;
     text-transform: lowercase;
}
 .elastic-wrap menu li a i {
    /* Allowances for icons if used before menu item text */
     opacity: 0.5;
     margin-right: 10px;
     text-align: center;
     min-width: 15px;
    /* Account for varying widths of icons and set them to display centered with one another */
}
 .elastic-wrap .menu .sub-menu a {
     font-size: 0.67em;
     margin-left: 25px;
}
/* Elastic Widget Sections */
 .elastic-wrap section {
     padding: 2em 0 2em 1em;
     background-color: #222222;
     color: #ffffff;
}
 .elastic-wrap section:not(.widget_nav_menu) {
     padding: 1em 0 2em 1em;
}
 .elastic-wrap section .widget-title, .elastic-wrap section .widgettitle, {
     font-weight: 700;
     text-transform: uppercase;
     font-size: 1em;
     line-height: 2.5em;
     letter-spacing: 1px;
}
 .elastic-wrap section p {
     font-size: 0.76em;
     line-height: 1.5em;
     font-weight: 300;
     margin-bottom: 1em;
}
/* Close Button */
 .elastic-wrap .close-button {
     width: 16px;
     height: 16px;
     position: absolute;
     top: 1em;
     right: 1em;
     overflow: hidden;
     text-indent: 16px;
     border: none;
     z-index: 1001;
     color: transparent;
     background: transparent;
}
 .elastic-wrap .close-button::before, .elastic-wrap .clsoe-button::after {
     content: '';
     position: absolute;
     width: 2px;
     height: 100%;
     top: 0;
     left: 50%;
     background: #dddddd;
}
 .elastic-wrap .close-button::hover {
     background: transparent;
}
 .elastic-wrap .close-button::hover::before, .elastic-wrap .close-button::hover::after {
     background: #ffffff;
}
 .elastic-wrap .close-button::before {
     -webkit-transform: rotate( 45deg );
     transform: rotate( 45deg );
}
 .elastic-wrap .close-button::after {
     -webkit-transform: rotate( -45deg );
     transform: rotate( -45deg );
}
/* Shown Menu */
 .show-menu .elastic-wrap {
     -webkit-transform: translate3d(0,0,0);
     transform: translate3d(0,0,0);
     width: 100%;
     overflow: scroll;
}
 .show-menu .site-container-wrap {
     -webkit-transition-delay: 0.1s;
     transition-delay: 0.1s;
     -webkit-transform: translate3d(330px,0,0);
     transform: translate3d(330px,0,0);
     opacity: 0.2;
}
 .show-menu .site-container::before {
     opacity: 1;
     -webkit-transition: opacity 0.3s;
     transition: opacity 0.3s;
     -webkit-transform: translate3d(0,0,0);
     transform: translate3d(0,0,0);
}
/* Assistive Text */
 .assistive-text {
     position: absolute;
     margin-left: -99999999%;
}
 @media all and min-width(55em) {
     .elastic-widget-wrap {
         width: 280px;
         padding-right: 0;
    }
     .show-menu .elastic-wrap {
         width: 400px;
         overflow: hidden;
    }
}
Code language: CSS (css)

Go play with this neat menu effect in a child theme, and don’t forget to tell me how you’ve tweaked it to suit your needs!

Similar Posts

Leave a Reply

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

4 Comments