Intro
Mobile menus have always been challenging, and over the last few years we’ve seen off-canvas menus, fixed navigation and everything in between.
Today, we’ll be looking at the “Top primary menu” in the Twenty Fourteen theme for WordPress, which is a fixed, top-down menu.
The Problem
I really like this style of menu, with one exception—large menus often go below the fold on mobile.
The Solution
One solution we are going to to explore here is making the menu accordion style on mobile.
Submenu items will be collapsed until the parent container is clicked/tapped, and then they will expand.
If a submenu is expanded, then a subsequent click on the active parent item will navigate to that page.
Shortcut
I highly recommend you read the entire article and get an understanding of what is going on, but if you just want the code it is on GitHub.
HTML
Since we are working with an existing theme, the HTML code is predefined. Below is the HTML code for the menu on the demo site:
[code language=”html”]
<nav class=”site-navigation primary-navigation” id=”primary-navigation” role=”navigation”>
<h1 class=”menu-toggle”>Primary Menu</h1>
<a class=”screen-reader-text skip-link” href=”#content”>Skip to content</a>
<div class=”menu-main-menu-container”>
<ul class=”nav-menu” id=”menu-main-menu”>
<li class=”menu-item menu-item-type-custom menu-item-object-custom current-menu-item current_page_item menu-item-home menu-item-278″ id=”menu-item-278″>
<a href=”http://twentyfourteendemo.wordpress.com/”>Home</a>
</li>
<li class=”menu-item menu-item-type-post_type menu-item-object-page menu-item-has-children menu-item-279″ id=”menu-item-279″><a href=”http://twentyfourteendemo.wordpress.com/a-parent-page/”>Dropdown Menu</a>
<ul class=”sub-menu”>
<li class=”menu-item menu-item-type-post_type menu-item-object-page menu-item-280″ id=”menu-item-280″>
<a href=”http://twentyfourteendemo.wordpress.com/a-parent-page/first-child/”>First Child</a>
</li>
<li class=”menu-item menu-item-type-post_type menu-item-object-page menu-item-has-children menu-item-282″ id=”menu-item-282″>
<a href=”http://twentyfourteendemo.wordpress.com/a-parent-page/second-child/”>Second Child</a>
<ul class=”sub-menu”>
<li class=”menu-item menu-item-type-post_type menu-item-object-page menu-item-283″ id=”menu-item-283″>
<a href=”http://twentyfourteendemo.wordpress.com/a-parent-page/second-child/a-grandchild-page/”>A Grandchild Page</a>
</li>
<li class=”menu-item menu-item-type-post_type menu-item-object-page menu-item-284″ id=”menu-item-284″>
<a href=”http://twentyfourteendemo.wordpress.com/a-parent-page/second-child/a-spoiled-grandchild-page/”>A Spoiled Grandchild Page</a>
</li>
<li class=”menu-item menu-item-type-post_type menu-item-object-page menu-item-285″ id=”menu-item-285″>
<a href=”http://twentyfourteendemo.wordpress.com/a-parent-page/second-child/another-grandchild-page/”>Another Grandchild Page</a>
</li>
</ul>
</li>
<li class=”menu-item menu-item-type-post_type menu-item-object-page menu-item-287″ id=”menu-item-287″>
<a href=”http://twentyfourteendemo.wordpress.com/a-parent-page/third-child/”>Third Child</a>
</li>
<li class=”menu-item menu-item-type-post_type menu-item-object-page menu-item-281″ id=”menu-item-281″>
<a href=”http://twentyfourteendemo.wordpress.com/a-parent-page/fourth-child/”>Fourth Child</a>
</li>
<li class=”menu-item menu-item-type-post_type menu-item-object-page menu-item-286″ id=”menu-item-286″>
<a href=”http://twentyfourteendemo.wordpress.com/a-parent-page/second-child/another-grandchild-page/a-wee-little-baby-page/”>A Wee Little Baby Page</a>
</li>
</ul>
</li>
<li class=”menu-item menu-item-type-post_type menu-item-object-page menu-item-has-children menu-item-357″ id=”menu-item-357″>
<a href=”http://twentyfourteendemo.wordpress.com/default-page-templates/”>Page Templates</a>
<ul class=”sub-menu”>
<li class=”menu-item menu-item-type-post_type menu-item-object-page menu-item-368″ id=”menu-item-368″>
<a href=”http://twentyfourteendemo.wordpress.com/default-page-templates/”>Default Page Templates</a>
</li>
<li class=”menu-item menu-item-type-post_type menu-item-object-page menu-item-358″ id=”menu-item-358″>
<a href=”http://twentyfourteendemo.wordpress.com/default-page-templates/contributor-page-template/”>Contributor Page Template</a>
</li>
<li class=”menu-item menu-item-type-post_type menu-item-object-page menu-item-359″ id=”menu-item-359″>
<a href=”http://twentyfourteendemo.wordpress.com/default-page-templates/full-width-page-template/”>Full width page template</a>
</li>
</ul>
</li>
<li class=”menu-item menu-item-type-post_type menu-item-object-page menu-item-289″ id=”menu-item-289″>
<a href=”http://twentyfourteendemo.wordpress.com/html-elements/”>HTML Elements</a>
</li>
<li class=”menu-item menu-item-type-post_type menu-item-object-page menu-item-290″ id=”menu-item-290″>
<a href=”http://twentyfourteendemo.wordpress.com/image-alignment-and-styles/”>Image Alignment and Styles</a>
</li>
</ul>
</div>
</nav>
[/code]
PHP
The only PHP we will have is a quick WordPress plugin file that uses wp_enqueue_script to load a Javascript file.
[code language=”php”]
<?php
/**
* Plugin Name: TwentyFourteen Accordion Menu
* Description: Adds accordion functionality to the Top primary menu in the TwentyFourteen theme on mobile
* Version: 1.0
* Author: Advice Interactive Group
* Author URI: http://www.adviceinteractivegroup.com
* License: GPL2
* Copyright 2014 Advice Interactive Group (email : info@adviceineractive.com)
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License, version 2, as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
function TwentyFourteen_Accordion_Menu_enqueue_scripts(){
// enqueue theme Javascript with jQuery as a dependency
// http://codex.wordpress.org/Function_Reference/wp_enqueue_script
wp_enqueue_script( ‘TwentyFourteen_Accordion_Menu’, plugins_url( ‘/js/TwentyFourteen_Accordion_Menu.js’ , __FILE__ ), array(‘jquery’), false, true );
}
// add enqueue_scripts to wp_enqueue_scripts action
// http://codex.wordpress.org/Plugin_API/Action_Reference/wp_enqueue_scripts
add_action( ‘wp_enqueue_scripts’, ‘TwentyFourteen_Accordion_Menu_enqueue_scripts’ );
?>
[/code]
Javascript
The Javascript is pretty straight forward as well. We will detect if we are on mobile by using the visibility of the menu toggle. If it is hidden, we are not on mobile and do nothing.
If we are on mobile, then we hide all submenus and add a click event to top level nav items containing a submenu.
When one is clicked (or tapped) it gets a class of “sub-menu-active” and the submenu is toggled on.
When the parent menu item is clicked again we check for the active class, and if it exists we return, which follows the link.
[code language=”javascript”]
function TwentyFourteen_Accordion_Menu(){
// if we are not on mobile (menu icon is hidden) show sub items and bail
if ( jQuery(‘#primary-navigation .menu-toggle’).is(‘:hidden’) ){
// show sub menus
jQuery(‘#menu-main-menu ul.sub-menu’).show();
return;
} else{
// hide sub menus
jQuery(‘#menu-main-menu ul.sub-menu’).hide();
}
// top level nav click function
jQuery(‘#menu-main-menu > li > a’).click(function(e){
// store parent li to variable
var parent_li = jQuery(this).parent(‘li’);
// if sub menu does not exist in parent li
if ( !jQuery(‘ul.sub-menu’, parent_li).first().length ) {
return;
}
// if sub menu is already active, bail
if ( parent_li.hasClass(‘sub-menu-active’) ){
return;
}
// stop link click
e.preventDefault();
// store current sub menu in variable
var current_submenu = jQuery(‘ul.sub-menu’, parent_li).first();
// slide up non-current sub menus
jQuery(‘#menu-main-menu > li > ul.sub-menu’).not(current_submenu).slideUp(function(){
// remove sub-menu-active class from all first level items except current parent li
jQuery(‘#menu-main-menu > li’).not(parent_li).removeClass(‘sub-menu-active’);
});
// slide down current sub menu
current_submenu.slideDown(function(){
// add sub-menu-active to current parent li
parent_li.addClass(‘sub-menu-active’);
});
});
// second level nav click function
jQuery(‘#menu-main-menu ul.sub-menu > li > a’).click(function(e){
// store parent li to variable
var parent_li = jQuery(this).parent(‘li’);
// if sub menu does not exist in parent li
if ( !jQuery(‘ul.sub-menu’, parent_li).first().length ) {
return;
}
// if sub menu is already active, bail
if ( parent_li.hasClass(‘sub-menu-active’) ){
return;
}
// stop link click
e.preventDefault();
// store current sub menu in variable
var current_submenu = jQuery(‘ul.sub-menu’, parent_li).first();
// slide up non-current sub menus
jQuery(‘#menu-main-menu ul.sub-menu > li > ul.sub-menu’).not(current_submenu).slideUp(function(){
// remove sub-menu-active class from all second level items except current parent li
jQuery(‘#menu-main-menu ul.sub-menu > li’).not(parent_li).removeClass(‘sub-menu-active’);
});
// slide down current sub menu
current_submenu.slideDown(function(){
// add sub-menu-active to current parent li
parent_li.addClass(‘sub-menu-active’);
});
});
}
// load menu accordion on doc ready
jQuery(document).ready(function($) {
TwentyFourteen_Accordion_Menu();
});
// load menu accordion on window resize
jQuery(window).resize(function(){
TwentyFourteen_Accordion_Menu();
});
[/code]
Summary
Our menu is now completely visible above the fold on mobile.
This was a pretty quick and easy way to extend the functionality of the menu and is a great example of a WordPress plugin. We accomplish a very specific task with code we can reuse on multiple projects without modifying the theme code.
Want to try it out for yourself? The entire code is on GitHub. Enjoy.
Thank you very much sir, Just what i needed