Hello!

In our many instances where we are developing, designing and deploying a WordPress site for a client, it is a constant necessity to implement a mobile / tablet friendly dropdown menu.

Because this happens often, we have developed a “starter” mobile menu for our WordPress implementations. We prefer to create a CSS based responsive mobile menu from scratch instead of using an out-of-the-box plugin because although the commercial (or free) WordPress menu plugin may make it much easier to roll out a mobile menu, as soon as the client comes to us with requests for customization, changes, positioning and styling it can become problematic.

This is because often times a WordPress plugin such as Superfly or Uber Menu will have their own stylesheets that are prioritized and sometimes difficult to override. This is also true with the built in jQuery effects such as slideouts, fade-ins and anything along those lines. Its not difficult to load a stylesheet or javascript file in the footer of the site, but that also can produce problems like delays in applying styles and effects which can cause a jittery or inconsistent user experience with the website.

So if you are 100% absolutely sure that what your client wants can be done without any issues with an out-of-the-box WordPress plugin, by all means go for it! Having it done from scratch once usually means that yes you can customize it as I’ve said, but you can also simply re-use what you’ve done in other projects as a starting point. So the “From scratch” approach can almost be just as convenient after you’ve done it once.

This is what we’re hoping to accomplish in this guide.

Step 1 : Add the mobile framework in header.php

Within the header.php in your WordPress theme, you will want to add the code snippet below. You can add it right above where you see the code for the regular menu. This will inject the framework for the mobile menu which you will later be able to style in the stylesheet

<!-- Mobile menu --> <div class="mobile-nav" id="nav-main-mobile"> <div class="menu-btn-container">. <div class="menu-btn" id="menu-btn"> <div></div> <span></span> <span></span> <span></span> <span id="menu-text">MENU</span> </div> </div> </div>. <div class="responsive-menu"> <?php $mobile_nav = array( 'theme_location' => '', 'menu' => '', 'container' => 'div', 'container_class' => 'menu-header', 'container_id' => '', 'menu_class' => 'menu', 'menu_id' => '', 'echo' => true, 'fallback_cb' => 'wp_page_menu', 'before' => '', 'after' => '', 'link_before' => '', 'link_after' => '', 'items_wrap' => '<ul id="%1$s" class="%2$s">%3$s</ul>', 'depth' => 0, 'walker' => '' ); wp_nav_menu( $mobile_nav ); ?> </div> </div> 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 < ! -- Mobile menu -- > < div class = "mobile-nav" id = "nav-main-mobile" > < div class = "menu-btn-container" > . < div class = "menu-btn" id = "menu-btn" > < div > < / div > < span > < / span > < span > < / span > < span > < / span > < span id = "menu-text" > MENU < / span > < / div > < / div > < / div > . < div class = "responsive-menu" > <?php $mobile_nav = array ( 'theme_location' = > '' , 'menu' = > '' , 'container' = > 'div' , 'container_class' = > 'menu-header' , 'container_id' = > '' , 'menu_class' = > 'menu' , 'menu_id' = > '' , 'echo' = > true , 'fallback_cb' = > 'wp_page_menu' , 'before' = > '' , 'after' = > '' , 'link_before' = > '' , 'link_after' = > '' , 'items_wrap' = > '<ul id="%1$s" class="%2$s">%3$s</ul>' , 'depth' = > 0 , 'walker' = > '' ) ; wp_nav_menu ( $mobile_nav ) ; ?> < / div > < / div >

What happening here? Well we’re encapsulating the navigation menu in a few CSS classes that we will later style. We will, by default, want to hide (display:none;) this menu in the stylesheet. Then we will use media queries to hide the desktop menu (assuming your desktop menu has its own custom css class we can hid) and show the mobile menu when the screen width hits a certain break point.

The function we are calling within the css containers is wp_nav_menu. You can read more about this WordPress function here. It takes a bunch of standard options as an array, as you can see in our example. You can manipulate the un-ordered list.

Step 2 : Style the menu

First, before anything, you want to hide the mobile menu entire container. This way no one will see it unless a media query triggers it. Then you can display the mobile menu and hide the desktop menu simultaneously for a seamless transition.

#nav-main-mobile { display: none !important; } 1 2 3 #nav-main-mobile { display : none ! important ; }

Now we want this mobile menu to be a simple black bar with a touch responsive (standard) menu icon in the top left. The dropdown will consist of the standard menu in a list, with a plus-sign on the right for people to know to trigger an expansion of sub navigation options.

The point you want this mobile menu to trigger is completely up to you. I’m going to implement styling that resembles the screenshot image above. You can add things like a search bar in the right side, or the site logo next to the menu icon on the left.

We’re going to trigger the menu if the screen width hits 768 pixels :

@media only screen and (max-width: 768px) { #nav-main-mobile { display: block; font-size:15px; top:0; position:absolute; z-index: 1000; background-color: #252525; width:100%; } #nav-main-mobile a { text-transform: uppercase; color: #fff; } #nav-main-mobile a:hover { color: #c50030; } #nav-main-mobile li { list-style-type: none; } /* =Nav -------------------------------------------------------------- */ .site-header { background-color: #252525; padding-top:30px; } .menu-item { width:100% !important; position: relative; padding: 0px; line-height:35px; } .menu-btn-container{ content:'menu'; text-transform:uppercase; color:#fff; padding:5px; } .menu-btn div { position: absolute; left: 100%; top: 64%; padding-right: 8px; margin-top: -0.50em; line-height: 1.2; font-size: 18px; font-weight: 200; vertical-align: middle; z-index: 99; } .menu-btn span { display: block; width: 19px; height: 3px; margin: 4px 0; background-color: #fff; z-index: 99; } .menu-btn #menu-text { display:block; float:left; position:absolute; top:2px; left:30px; background-color: #252525; } .responsive-menu{ display: none; } .expand { display: block !important;. } .open-menu-link{ display: none; position: absolute; right: 15px; top:0; line-height: 35px; font-size: 30px; cursor: pointer; } li .sub-menu{ display: none; } li .sub-menu a { font-size: 12px; list-style-type: none !important;} .visible { display: block !important; color: #fff; } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 @ media only screen and ( max - width : 768px ) { #nav-main-mobile { display : block ; font - size : 15px ; top : 0 ; position : absolute ; z - index : 1000 ; background - color : #252525; width : 100 % ; } #nav-main-mobile a { text - transform : uppercase ; color : #fff; } #nav-main-mobile a:hover { color : #c50030; } #nav-main-mobile li { list - style - type : none ; } /* =Nav -------------------------------------------------------------- */ . site - header { background - color : #252525; padding - top : 30px ; } . menu - item { width : 100 % ! important ; position : relative ; padding : 0px ; line - height : 35px ; } . menu - btn - container { content : 'menu' ; text - transform : uppercase ; color : #fff; padding : 5px ; } . menu - btn div { position : absolute ; left : 100 % ; top : 64 % ; padding - right : 8px ; margin - top : - 0.50em ; line - height : 1.2 ; font - size : 18px ; font - weight : 200 ; vertical - align : middle ; z - index : 99 ; } . menu - btn span { display : block ; width : 19px ; height : 3px ; margin : 4px 0 ; background - color : #fff; z - index : 99 ; } . menu - btn #menu-text { display : block ; float : left ; position : absolute ; top : 2px ; left : 30px ; background - color : #252525; } . responsive - menu { display : none ; } . expand { display : block ! important ; . } . open - menu - link { display : none ; position : absolute ; right : 15px ; top : 0 ; line - height : 35px ; font - size : 30px ; cursor : pointer ; } li . sub - menu { display : none ; } li . sub - menu a { font - size : 12px ; list - style - type : none ! important ; } . visible { display : block ! important ; color : #fff; } }

The end result is a really simple, clean and functional mobile friendly menu. You can add jQuery animation to the slide-out or expansion actions if you wanted. In this example we wanted to keep a lean and fast mobile menu. This is a great starting point that can be expanded to many different options. The advantages again of this solution is that you’re not restricted by constraints or overrides from a plugin and can accommodate client revisions or feedback much more freely.

I hope this helps!