Making The WordPress Twenty Fourteen Theme Sexier With A Mobile Accordion Menu

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.
twenty-fourteen-top-primary-menu-iphone

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:

<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>

PHP

The only PHP we will have is a quick WordPress plugin file that uses wp_enqueue_script to load a Javascript file.

<?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' );

?>

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.

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();
});

Summary

Our menu is now completely visible above the fold on mobile.

twenty-fourteen-top-primary-menu-accordion-iphone

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.

1 Comment
  1. Mohamed saleh says:

    Thank you very much sir, Just what i needed

Recent Blog Posts in realtime
Google announces the long anticipated Penguin 4.0 update today on the Webmaster Central Blog. Penguin Now Part of the Core Algorithm Penguin joins Panda as part of the core Google algorithm. Gone...
Over the past year, we’ve been evangelizing – sharing the good news about businesses taking control of online data. And we dedicated lots of resources to educating businesses and brands, teaching them...
Have you heard yet that we’re making some changes? One of our brands, Local Site Submit, is rebranding to Advice Local. Preparations for the transition are almost complete and our new, expanded...