Calvin Koepke
/* Step 4: Animate That Menu!
/* In your style.css file, add the following (I’ll explain at the bottom what’s going on):
/*
Title: How to Add a Mobile-Friendly, Off Canvas Menu in Genesis
Author: Calvin Koepke (@cjkoepke)
Link: http://www.calvinkoepke.com/add-a-mobile-friendly-off-canvas-menu-in-genesis
*/
/* Animation Settings and Classes
--------------------------------------------- */
.off-canvas-active,
.off-canvas-active .site-container{
overflow: hidden;
}
.nav-primary,
.site-container {
-webkit-transition: all .2ss ease-in-out;
-moz-transition: all .2ss ease-in-out;
-ms-transition: all .2ss ease-in-out;
-o-transition: all .2ss ease-in-out;
transition: all .2ss ease-in-out;
}
.nav-primary {
-webkit-transform: translateX(260px);
-moz-transform: translateX(260px);
-ms-transform: translateX(260px);
-o-transform: translateX(260px);
transform: translateX(260px);
}
.off-canvas-active .nav-primary,
.site-container {
-webkit-transform: translateX(0);
-moz-transform: translateX(0);
-ms-transform: translateX(0);
-o-transform: translateX(0);
transform: translateX(0);
}
.off-canvas-active .site-container {
-webkit-transform: translateX(-260px);
-moz-transform: translateX(-260px);
-ms-transform: translateX(-260px);
-o-transform: translateX(-260px);
transform: translateX(-260px);
}
/* Site Overlay
--------------------------------------------- */
.site-overlay {
display: none;
}
.off-canvas-active .site-overlay {
display: block;
position: fixed;
top: 0;
right: 260px;
bottom: 0;
left: 0;
width: 100%;
height: 100%;
z-index: 9998;
}
//* Do NOT include the opening PHP tag
/**
* Include the JavaScript
* @author Calvin Koepke (@cjkoepke)
* @link http://www.calvinkoepke.com/add-a-mobile-friendly-off-canvas-menu-in-genesis
*/
add_action( 'wp_enqueue_scripts', 'ck_load_menu' );
function ck_load_menu() {
wp_enqueue_script( 'ck-menu', get_stylesheet_directory_uri() . '/js/offcanvas-nav.js', array( 'jquery' ), 1.0 );
//* Also include Dashicons for the iconography
wp_enqueue_style( 'dashicons' );
}
Don’t worry about too many of the details, but the basic idea of what’s going on is this:
Look for click events on our designated triggers (the Menu Button and Close Button )
Once one of these triggers are clicked, add or remove a class to the body tag
The rest is completely handled in CSS. Before we can move onto the next stage, though, let’s queue up our new JS file to load in the head of our document. Add this to your functions.php file:
Note: You’ll notice that I also include the WordPress Dashicons into the below script. This is because I use them in the markup for the “Menu” and the “Close” buttons.
//* Step 2: Add JavaScript to Our Mobile Menu
//* Before we get to the styling of everything, let’s get the JavaScript out of the way. It’s a pretty simple series of functions and you’ll see explanations of everything in the code below.
//* Create a new file in your theme (in our case, within a /js subfolder), and name it offcanvas-nav.js. Then, add the following and hit Save:
jQuery( document ).ready( function( $ ) {
// @author Calvin Koepke (@cjkoepke)
// @link http://www.calvinkoepke.com/add-a-mobile-friendly-off-canvas-menu-in-genesis/
// @version 1.1
// @license Free to use as you wish. Please share if you appreciate and link to the post above.
// Store our jQuery objects as variables
var body = $( 'body' ),
toggleButtons = $( '.menu-btn, .close-btn, .site-overlay' );
toggleButtons.click( function( event ) {
// Prevent the default action of clicking a link
event.preventDefault();
// Toggle our main body class depending on whether it is present (false by default)
body.toggleClass( 'off-canvas-active' );
});
});
//* Do NOT include the opening PHP tag
/**
* Add the overlay div that will be used for clicking out of the active menu.
* @author Calvin Koepke (@cjkoepke)
* @link http://www.calvinkoepke.com/add-a-mobile-friendly-off-canvas-menu-in-genesis
*/
add_action( 'genesis_before', 'ck_site_overlay', 2 );
function ck_site_overlay() {
echo '<div class="site-overlay"></div>';
}
A little trick I like to do when dealing with toggled-interfaces is to provide an easy way to return to the original state. In this case, that means creating a click-event on the main page content that will close the menu (but only if it’s open).
I do this through a hidden div that acts as an overlay, or by tying a click event to the .site-container element. If I add a blank div, it’s because I want that to be an overlay that signals the rest of the content is not accessible when the menu is open.
So let’s add that empty div right after the Primary Navigation so it covers everything else:
//* Next, we need to add the actual “Menu” button to our header, and add the “Close navigation” text inside the Primary Navigation.
//* Do NOT include the opening PHP tag
/**
* Add the menu to the .site-header, but hooking right before the genesis_header_markup_close action.
* @author Calvin Koepke (@cjkoepke)
* @link http://www.calvinkoepke.com/add-a-mobile-friendly-off-canvas-menu-in-genesis
*/
add_action( 'genesis_header', 'ck_menu_button', 14 );
function ck_menu_button() {
//* Only add the Menu button if a primary navigation is set. You can switch this for whatever menu you are dealing with
if ( has_nav_menu( "primary" ) ) {
echo '<a alt="Toggle Menu" href="#" class="menu-btn right small">' . __( 'Menu', 'CHILD_THEME_TEXT_DOMAIN' ) . '<span class="dashicons dashicons-menu"></span></a>';
}
}
//* Add the "Close Navigation" text to the Primary menu output.
add_filter( 'genesis_nav_items', 'ck_close_btn', 10, 2 );
add_filter( 'wp_nav_menu_items', 'ck_close_btn', 10, 2 );
function ck_close_btn($menu, $args) {
$extras = '<a href="#" class="close-btn"><em>' . __( 'Close Navigation', 'CHILD_THEME_TEXT_DOMAIN' ) . '</em> <span class="dashicons dashicons-no"></span></a>';
if ( $args->theme_location == "primary" ) {
return $extras . $menu;
} else {
return $menu;
}
}
//* https://calvinkoepke.com/add-a-mobile-friendly-off-canvas-menu-in-genesis/
//* Step 1: Build the Basic Mobile Menu Markup
//* First, let’s place the navigation at the top of the page (technically not necessary since the nav will be position: fixed;, but I like things clean).
//* Add the following code into your functions.php file to move the Primary Navigation to right after the opening body tag:
//* Do NOT include the opening PHP tag
/**
* Reposition the Primary navigation at the top of the DOM.
* @author Calvin Koepke
* @link http://www.calvinkoepke.com/add-a-mobile-friendly-off-canvas-menu-in-genesis
*/
remove_action( 'genesis_after_header', 'genesis_do_nav' );
add_action( 'genesis_before', 'genesis_do_nav', 1 );
/*
Title: How to Add a Mobile-Friendly, Off Canvas Menu in Genesis
Author: Calvin Koepke (@cjkoepke)
Link: http://www.calvinkoepke.com/add-a-mobile-friendly-off-canvas-menu-in-genesis
*/
/* Genesis Navigation Menu
--------------------------------------------- */
.genesis-nav-menu {
font-size: 16px;
line-height: 1;
list-style: none;
margin: 0;
padding-bottom: 40px;
}
.genesis-nav-menu .menu-item {
margin: 0;
}
.genesis-nav-menu .menu-item a {
display: block;
color: #ffffff;
padding: 10px 40px;
font-family: "Raleway", sans-serif;
font-weight: 600;
font-size: 16px;
text-transform: uppercase;
border-bottom: none;
opacity: .6;
/* Transitions */
-webkit-transition: all .15s ease-in-out;
-moz-transition: all .15s ease-in-out;
-ms-transition: all .15s ease-in-out;
-o-transition: all .15s ease-in-out;
transition: all .15s ease-in-out;
}
.genesis-nav-menu .menu-item a:hover {
opacity: 1;
color: #fff;
}
.genesis-nav-menu .current-menu-item > a,
.genesis-nav-menu .sub-menu .current-menu-item > a:hover {
opacity: 1;
}
.genesis-nav-menu .sub-menu {
display: block;
}
.genesis-nav-menu .sub-menu a {
display: block;
font-size: .9em;
line-height: 1.2em;
text-transform: none;
font-weight: normal;
margin-left: 20px;
-webkit-font-smoothing: antialiased;
}
.genesis-nav-menu .menu-item:hover {
position: static;
}
/* Primary Navigation
--------------------------------------------- */
.nav-primary {
position: fixed;
width: 260px;
height: 100%;
top: 0;
right: 0;
z-index: 9999;
background: #010101;
overflow: auto;
-webkit-overflow-scrolling: touch;
}
.nav-primary a {
color: #fff;
}
.nav-primary a:hover,
.nav-primary .current-menu-item > a,
.nav-primary .sub-menu .current-menu-item > a:hover {
color: #cb6c28;
}
/* Menu Button
--------------------------------------------- */
.site-header > .wrap {
position: relative;
}
.menu-btn {
position: absolute;
top: 40%;
right: 0;
color: #000;
}
.menu-btn:hover,
.off-canvas-active .menu-btn {
color: #e5554e;
}
.menu-btn span {
line-height: 1.6;
}
/* Close Button
--------------------------------------------- */
.nav-primary .close-btn {
color: #fff;
display: block;
opacity: .4;
font-weight: 300;
font-style: italic;
font-family: "Roboto Slab", serif;
font-size: 16px;
padding: 50px 40px 20px;
}
.nav-primary .close-button:hover {
text-decoration: none;
opacity: 1;
color: #fff;
}
.nav-primary .close-button span {
float: right;
font-size: 16px;
margin-top: 2px;
font-weight: normal;
}
Step 3: Styling the Menu to be Mobile Friendly
The beauty of this off-canvas menu is that all the animation happens with pure CSS, which is minimal at that. But before we get to the animation, we need the Primary Navigation to be vertically aligned and full-height.
This also allows for scrolling if the navigation gets too high, something that is impossible with horizontal navigations and inherently mobile-friendly.
We’ll add more styling in a bit for opening and closing the navigation, like I said, but for now copy and paste this into your style.css file. You can tweak it to match the style of your site if you want—just keep the main structure properties:
Note: Make sure that you either paste this styling at the bottom of your stylesheet to override defaults, or (better option) manually replace the styling in your child theme with what’s below.