The built in Menu blocks in Oxygen are a bit limited with regards to control and styling for small screens. I decided to try and build my own responsive mobile menu. I also wanted to make sure that the mobile menu had support for secondary, or even tertiary level, menu items. THis allows me to completely customise the menu appearance using css, and not be restricted in any way.
The end result looks like this:
See the Pen Slide-in mobile menu with sub-menus + by Titus (@titus) on CodePen.
It's fairly simple to add this to Oxygen. First of all though, we need to add a function to register_nav_menus. This allows us to define a 'location' for the menu so that we can assign it to appear in the mobile menu. You'll need to place this in Code Snippets, Advanced Scripts, or a plugin functions.php file.
//Add support for nav menus
add_theme_support( 'nav-menus' );
if ( function_exists( 'register_nav_menus' ) )
{
register_nav_menus(
array(
'primary_nav' => 'Primary Navigation',
)
);
}
In your Oxygen template, add a Code Block, and paste in the following code. The first part displays the hamburger button and the second section contains the php to display a standard Wordpress menu.
<!-- hamburger button -->
<div class="showhide">
<div class="showhide--inner">
<span class="ham1"></span>
<span class="ham2"></span>
<span class="ham3"></span>
</div>
</div>
<!-- mobile menu -->
<div class="mobilenav--wrap">
<div class="mobilenav">
<?php
if(function_exists('wp_nav_menu')):
wp_nav_menu(
array(
'menu' =>'primary_nav',
'theme_location' => 'primary_nav',
'container'=>'',
'depth' => 2,
'menu_id' => 'menu' )
);
endif;
?>
</div>
</div>
If need be, you can separate this into two blocks. You could create one Code Block with the hamburger button, and another with the mobile menu. In fact if you create a div in Oxygen with a class of mobilenav--wrap, you could then nest a Code Block inside with the mobile menu (just remove the outer div with the mobilenav--wrap class) and add any other elements you like (i.e. logo, or call-to-action etc.)
Then add the following CSS to the Code block...
/* mobile menu hamburger button */
.showhide {
background: #efefef;
width: 46px;
height: 46px;
position: absolute;
top: 0;
right: 0;
cursor: pointer;
z-index: 999999;
}
.showhide:hover {
background: #fff;
}
.showhide--inner {
margin: 9px;
position: relative;
box-sizing: border-box;
width: 32px;
height: 32px;
display: block;
}
.showhide span {
position: absolute;
background: #333;
height: 2px;
width: 28px;
transition: 0.5s;
opacity: 1;
}
.showhide span.ham1 {top: 4px}
.showhide span.ham2 {top: 14px}
.showhide span.ham3 {top: 24px}
.showhide.open span.ham1 {
-moz-transform: rotate(45deg);
-webkit-transform: rotate(45deg);
-o-transform: rotate(45deg);
-ms-transform: rotate(45deg);
transform: rotate(45deg);
top:14px;
}
.showhide.open span.ham2 {opacity: 0}
.showhide.open span.ham3 {
-moz-transform: rotate(-45deg);
-webkit-transform: rotate(-45deg);
-o-transform: rotate(-45deg);
-ms-transform: rotate(-45deg);
transform: rotate(-45deg);
top:14px;
}
/* mobile menu container */
.mobilenav--wrap {
padding: 0;
width: 320px;
height: 100vh;
background: #efefef;
-webkit-box-shadow: 0 0 3px 0 rgba(0,0,0,0.3);
box-shadow: 0 0 3px 0 rgba(0,0,0,0.3);
top: 0;
right: -320px;
position: fixed;
-webkit-transition: all 0.3s ease;
-moz-transition: all 0.3s ease;
-ms-transition: all 0.3s ease;
-o-transition: all 0.3s ease;
transition: all 0.3s ease;
}
.mobilenav--wrap.show--mobilenav {
right: 0;
}
/* mobile menu */
.mobilenav {
width: 100%;
height: 100%;
overflow: scroll;
padding: 0;
}
.mobilenav > ul {
width: 100%;
box-sizing: border-box;
margin: 6rem 0 2rem 0;
}
.mobilenav ul li {
position: relative;
border-bottom: 1px solid #ccc;
list-style:none;
font-size: 1.6rem
}
.mobilenav ul li a {
display: block;
padding: 15px 20px;
text-decoration: none;
color: #333
}
.mobilenav ul li a:hover {
background: #fff;
color: red;
}
.mobilenav ul li:hover ul {
display:block;
margin-left: 0;
}
.mobilenav ul ul li {
border-top: 1px dotted #ccc;
border-bottom: 0;
position: relative;
font-size: 90%;
}
.mobilenav ul ul {
padding-left: 15px;
}
a.menu-expand {
padding: 0 !important;
background: transparent !important;
width: 44px;
height: 44px;
position: absolute;
top: 0;
right: 0;
z-index: 100;
}
.mobilenav ul li.menu-item-has-children .plus1{
content: '';
position: absolute;
right: 10px;
top: 24px;
width: 20px;
height: 2px;
display: block;
background: #000;
transition: all 0.3s ease-in-out;
transform: rotate(-180deg);
}
.mobilenav ul li.menu-item-has-children .plus2{
content: '';
position: absolute;
right: 10px;
top: 24px;
width: 20px;
height: 2px;
display: block;
background: #000;
transition: all 0.3s ease-in-out;
transform: rotate(-270deg);
}
a.menu-expand:hover span {
background: red !important;
}
.mobilenav ul li.menu-item-has-children > a.menu-expand.menu-clicked .plus1 {
transform: rotate(0);
}
.mobilenav ul li.menu-item-has-children > a.menu-expand.menu-clicked .plus2{
transform: rotate(0);
}
And lastly, add this Javascript to the Code block... If you don't have tertiary-level menu items, you can enable lines 21 and 22 (remove the double forward slash at the beginning of the line) so that the menu works more like an accordion – opening one menu will automatically close the others.
///////////////////////////////////////////////
//show and hide mobile menu
///////////////////////////////////////////////
jQuery(".showhide").click(function(){
jQuery(this).toggleClass("open");
jQuery(".mobilenav--wrap").toggleClass( "show--mobilenav" );
});
//hide sub-menus
jQuery('.mobilenav ul ul').hide();
jQuery('.mobilenav ul.sub-menu').each(function() {
if(jQuery(this).children().length){
jQuery(this,'li:first').parent().append('<a class="menu-expand" href="#" style="font-size:26px"><span class="plus1"></span><span class="plus2"></span></a>');
}
});
jQuery('.mobilenav ul li.menu-item-has-children > a.menu-expand').on("click",function(e){
//enable these two lines if you only have one sub-menu level - closes other menus
//jQuery (".menu-clicked").not(this).removeClass("menu-clicked");
//jQuery('ul.sub-menu').slideUp(300, function(){});
e.preventDefault();
if (jQuery(this).hasClass("menu-clicked")) {
jQuery(this).removeClass("menu-clicked");
jQuery(this).prev('ul').slideUp(300, function(){});
} else {
jQuery(this).addClass("menu-clicked");
jQuery(this).prev('ul').slideDown(300, function(){});
}
});
Of course, you can select to make this Code block only appear on smaller screens, and use the standard Oxygen menu for large desktop screens. Set the Code Block to be hidden (Advanced > Layout > Display > none) on desktop, and set it to be visible on smaller screens (Display > block).
If you have a desktop menu you can do the opposite so that they compliment each other.
Specialising in responsive Wordpress website design, development, hosting, site optimisation, digital marketing, as well as graphic design for print.