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!
Nice I like it a lot !!!!! Sweet work indeed and thanks for sharing ! 😉
Great guide! I have a project I want to try this one out on. It should work splendid with a canvas off menu like this.
Thanks for sharing!
be interesting to see him shoot a subject of genesis.
Thank you
I have tried incorporating your tutorial and files into a plain/new version of genesis sample child theme and it just doesn’t work. See screenshot: http://imgur.com/NTuKdDD