Genesis Responsive Menu: Accessible Edition

Genesis 2.2 was released a short while ago, and some of its most significant work went into making it accessible for users with disabilities (major props to Rian Rieltveld, who was the powerhouse behind this work). Accessibility is not just a feature–it’s a mindset, so support for it has to be intentionally added to your child theme. Rian wrote a great post about extending this functionality to your child theme.

Brad Potter raised the issue on Twitter, though, that the new accessibility features seem to cause some usability issues with the existing Genesis responsive menu solutions and tutorials. Discussions have ensued, and there has been a bit of frustration (from all of us) that enabling accessibility has not necessarily been as easy as adding just a few lines of code.

Although I’m really here to write a tutorial, I’d like to say that significant new features are usually not that easy to incorporate into existing structures. There are reasons why older StudioPress themes are still XHTML instead of being switched over to HTML5, or are still not responsive. Accessibility is not an afterthought.

We haven’t seen new child themes from StudioPress since 2.2 was released, so I don’t yet know how they’ll handle mobile menus, but generally, responsive navigation is implemented uniquely for each theme. The Genesis Sample theme, for example, does not implement a specific mobile menu at all.

So Brad raised the question of how to take a great mobile responsive menu solution (we are big fans of Ozzy Rodriguez’s menu as a starting point), and make it play well with the new Genesis accessibility support. He made great progress on taking the Superfish script out of the question, as that seemed to be what was causing the issues, but there are some other factors to take into account. So, I thought I’d join in the fun.

The challenge: to create a Genesis responsive menu which works well with the existing framework accessibility features, such as the drop down menu support and new skip links support.

Challenge accepted.

Side note: this is completely unrelated to the work I’ve done with SuperSide Me, my own preferred mobile menu option. That is a fairly accessible menu, but as it’s a completely separate system from Genesis, it’s not affected by this. Also, although I love SuperSide Me and recommend it to anyone who wants a super easy mobile menu, I’ll be the first to admit that it’s not the best option for every site. So I too would like to have a solid solution in place for child themes.

So let’s dive in.

Start with Skip Links

What is a skip link? You’ll know if you read Rian’s post, but briefly, here’s her definition: “Skip links are used by people who navigate a website without a mouse, with a keyboard only and by screen reader users. You can use a skip link to quickly jump to for example the main content or the footer.” If you’ve added support for skip links to your child theme, they’ve automatically been added for your primary navigation and main content, and primary sidebar or footer widgets if you use them. But what if you’ve added more menus, like a secondary menu? Well, you can add skip links yourself with a couple of functions:

// Add skip link needs to secondary nav add_filter( 'genesis_attr_nav-secondary', 'leaven_add_nav_secondary_id' ); function leaven_add_nav_secondary_id( $attributes ) { $attributes['id'] = 'genesis-nav-secondary'; return $attributes; } add_filter( 'genesis_skip_links_output', 'leaven_add_nav_secondary_skip_link' ); function leaven_add_nav_secondary_skip_link( $links ) { $new_links = $links; array_splice( $new_links, 1 ); if ( has_nav_menu( 'secondary' ) ) { $new_links['genesis-nav-secondary'] = __( 'Skip to secondary navigation', 'leaven' ); } return array_merge( $new_links, $links ); }
Code language: PHP (php)

Note on the above: we need to add an ID to the secondary navigation menu so that the new link we create has a place to actually land. Now, these functions are nice in that they’ll only come into play if you have a menu assigned to your secondary navigation.

Do you need to add any skip links to your functions.php file? That depends. If you want screen reader users to be able to find your new element, such as your secondary navigation, then yes.

A New Responsive Navigation Script

Genesis Responsive Menu: Accessible Edition

The biggest challenge of this entire project was to revamp Ozzy’s script to account for the accessibility features. Brad figured out how to stop the Superfish script from causing wonky hover effects on submenus, which was significant. However, because the navigation is all hidden on mobile, it breaks the navigation skip links, because their target is also hidden.

Ideally, I wanted to end up with a script that could be dropped into any child theme, accessibility enabled or not, and not have to edit it. So one more piece of the puzzle was to make the script screen-size agnostic–a lot of responsive menu solutions have a screen width hard coded into the JavaScript. What if I could make it just work, without caring whether the child theme wanted the mobile menu to happen at 768, 800, or 960 pixels? Most of that is controlled in the CSS anyway, so ideally, I could keep it out of the script.

I think the following script accomplishes these goals:

  1. honor skip links, no matter what child theme is used, and however many navigation menus the theme adds
  2. disable Superfish as needed so that the hover doesn’t kill the mobile menu functionality
  3. not related to accessibility at all, but a feature I just want: if a submenu is open, and then you open a different one, the first submenu closes
( function ( document, $, undefined ) { 'use strict'; var leaven = {}, mainMenuButtonClass = 'menu-toggle', subMenuButtonClass = 'sub-menu-toggle'; leaven.init = function() { var toggleButtons = { menu : $( '<button />', { 'class' : mainMenuButtonClass, 'aria-expanded' : false, 'aria-pressed' : false, 'role' : 'button' } ) .append( leaven.params.mainMenu ), submenu : $( '<button />', { 'class' : subMenuButtonClass, 'aria-expanded' : false, 'aria-pressed' : false, 'role' : 'button' } ) .append( $( '<span />', { 'class' : 'screen-reader-text', text : leaven.params.subMenu } ) ) }; $( 'nav' ).before( ); // add the main nav buttons $( 'nav .sub-menu' ).before( toggleButtons.submenu ); // add the submenu nav buttons $( '.' + mainMenuButtonClass ).each( _addClassID ); $( window ).on( 'resize.leaven', _doResize ).triggerHandler( 'resize.leaven' ); $( '.' + mainMenuButtonClass ).on( 'click.leaven-mainbutton', _mainmenuToggle ); $( '.' + subMenuButtonClass ).on( 'click.leaven-subbutton', _submenuToggle ); }; // add nav class and ID to related button function _addClassID() { var $this = $( this ), nav = $ 'nav' ), id = 'class'; $this.addClass( $( nav ).attr( 'class' ) ); if ( $( nav ).attr( 'id' ) ) { id = 'id'; } $this.attr( 'id', 'mobile-' + $( nav ).attr( id ) ); } // Change Skiplinks and Superfish function _doResize() { var buttons = $( 'button[id^=mobile-]' ).attr( 'id' ); if ( typeof buttons === 'undefined' ) { return; } _superfishToggle( buttons ); _changeSkipLink( buttons ); _maybeClose( buttons ); } /** * action to happen when the main menu button is clicked */ function _mainmenuToggle() { var $this = $( this ); _toggleAria( $this, 'aria-pressed' ); _toggleAria( $this, 'aria-expanded' ); $this.toggleClass( 'activated' ); $ 'nav, .sub-menu' ).slideToggle( 'fast' ); } /** * action for submenu toggles */ function _submenuToggle() { var $this = $( this ), others = $this.closest( '.menu-item' ).siblings(); _toggleAria( $this, 'aria-pressed' ); _toggleAria( $this, 'aria-expanded' ); $this.toggleClass( 'activated' ); $ '.sub-menu' ).slideToggle( 'fast' ); others.find( '.' + subMenuButtonClass ).removeClass( 'activated' ).attr( 'aria-pressed', 'false' ); others.find( '.sub-menu' ).slideUp( 'fast' ); } /** * activate/deactivate superfish */ function _superfishToggle( buttons ) { if ( typeof $( '.js-superfish' ).superfish !== 'function' ) { return; } if ( 'none' === _getDisplayValue( buttons ) ) { $( '.js-superfish' ).superfish( { 'delay': 100, 'animation': {'opacity': 'show', 'height': 'show'}, 'dropShadows': false }); } else { $( '.js-superfish' ).superfish( 'destroy' ); } } /** * modify skip links to match mobile buttons */ function _changeSkipLink( buttons ) { var startLink = 'genesis-nav', endLink = 'mobile-genesis-nav'; if ( 'none' === _getDisplayValue( buttons ) ) { startLink = 'mobile-genesis-nav'; endLink = 'genesis-nav'; } $( '.genesis-skip-link a[href^="#' + startLink + '"]' ).each( function() { var link = $( this ).attr( 'href' ); link = link.replace( startLink, endLink ); $( this ).attr( 'href', link ); }); } function _maybeClose( buttons ) { if ( 'none' !== _getDisplayValue( buttons ) ) { return; } $( '.menu-toggle, .sub-menu-toggle' ) .removeClass( 'activated' ) .attr( 'aria-expanded', false ) .attr( 'aria-pressed', false ); $( 'nav, .sub-menu' ) .attr( 'style', '' ); } /** * generic function to get the display value of an element * @param {id} $id ID to check * @return {string} CSS value of display property */ function _getDisplayValue( $id ) { var element = document.getElementById( $id ), style = window.getComputedStyle( element ); return style.getPropertyValue( 'display' ); } /** * Toggle aria attributes * @param {button} $this passed through * @param {aria-xx} attribute aria attribute to toggle * @return {bool} from _ariaReturn */ function _toggleAria( $this, attribute ) { $this.attr( attribute, function( index, value ) { return _ariaReturn( value ); }); } /** * update aria-xx value of an attribute * @param {aria-xx} value passed from function * @return {bool} */ function _ariaReturn( value ) { return 'false' === value ? 'true' : 'false'; } $(document).ready(function () { leaven.params = typeof LeavenL10n === 'undefined' ? '' : LeavenL10n; if ( typeof leaven.params !== 'undefined' ) { leaven.init(); } }); })( document, jQuery );
Code language: JavaScript (javascript)

You can copy this entire file and put it in your child theme (I have a /js/ folder in my child theme). No edits needed. Seriously. The script makes certain modifications based on whether the mobile menu buttons are actually visible, which you’ll handle in your CSS. So change your CSS; this will still work.

Enqueue All the Things, I Mean Scripts

Your new mobile menu script isn’t going to work yet, because you still have to add it to your theme. That’s over in your functions.php file. Add this function, or modify your existing enqueue function, to this:

// Required Scripts and Styles add_action( 'wp_enqueue_scripts', 'leaven_load_scripts', 15 ); function leaven_load_scripts() { // Responsive Navigation wp_enqueue_style( 'fontawesome', '//', array(), '4.3.0' ); wp_enqueue_script( 'leaven-responsive-menu', get_stylesheet_directory_uri() . '/js/responsive-menu.js', array( 'jquery' ), '1.0.0', true ); $output = array( 'mainMenu' => __( 'Menu', 'leaven' ), 'subMenu' => __( 'Menu', 'leaven' ), ); wp_localize_script( 'leaven-responsive-menu', 'LeavenL10n', $output ); }
Code language: PHP (php)

You do not have to use Font Awesome, but it’s in there because it’s what I use in my theme. Also, the $output variables are incredibly important–without them, your shiny responsive navigation script will not run. We set them up in PHP so that we can make them available to translators if we need to. They are the labels for the main menu button (visible) and the submenu buttons (hidden, but available for screen readers).

Mobile Menu Styling

Depending on your theme, this last bit may need more or less adjusting on your part, and it’s the styling. I’ve put together what I found to be the minimum necessary to get this up and running on the Genesis Sample theme:

/* # Responsive Navigation ---------------------------------------------------------------------------------------------------- */ /* Navigation toggles --------------------------------------------- */ .sub-menu-toggle, .menu-toggle { display: none; visibility: hidden; } @media only screen and (max-width: 800px) { nav { display: none; position: relative; } nav .wrap { padding: 0; } nav.pagination { display: block; } .menu-toggle, .sub-menu-toggle { display: block; visibility: visible; overflow: hidden; margin: 0 auto; font-size: 20px; font-weight: 700; text-align: center; background-color: transparent; } .menu-toggle { background-color: #333; position: relative; padding: 20px 12px; right: 0; z-index: 1000; color: white; width: 100%; } .menu-toggle:before, .menu-toggle.activated:before { display: inline-block; font: normal normal normal 20px FontAwesome; text-rendering: auto; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; -webkit-transform: translate(0, 0); -ms-transform: translate(0, 0); transform: translate(0, 0); content: "\f0c9"; padding-right: 12px; } .sub-menu-toggle { background: transparent; float: right; position: absolute; top: 0; right: 0; padding: 18px; z-index: 100; } .sub-menu-toggle:before { display: inline-block; font: normal normal normal 16px FontAwesome; text-rendering: auto; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; -webkit-transform: translate(0, 0); -ms-transform: translate(0, 0); transform: translate(0, 0); content: "\f107"; } .sub-menu-toggle.activated:before { content: "\f106"; } .genesis-nav-menu .menu-item { display: block; position: relative; text-align: left; } .genesis-nav-menu .menu-item a { border-top: 1px solid rgba(0, 0, 0, 0.1); border-bottom: 1px solid rgba(255, 255, 255, 0.1); width: 100%; padding: 20px; } .genesis-nav-menu .menu-item:hover { position: relative; } .genesis-nav-menu .menu-item > a:focus ul.sub-menu, .genesis-nav-menu .menu-item > a:focus ul.sub-menu .sub-menu { left: 0; margin-left: 0; } .genesis-nav-menu > .menu-item-has-children > a:after { content: none; } .genesis-nav-menu .sub-menu { display: none; clear: both; margin: 0; position: static; width: 100%; opacity: 1; } .genesis-nav-menu .sub-menu .sub-menu { margin: 0; } .genesis-nav-menu .sub-menu a { border-left: none; border-right: none; padding-left: 40px; color: #eee; } .nav-primary .genesis-nav-menu .sub-menu a { background-color: #333; color: #eee; } }
Code language: CSS (css)

Want to change where the menu changes to the mobile menu? Just change the 800px to your preferred value, whatever that may be.

Even if you do not have accessibility support enabled in your theme, this script will still work. If you have added support for either or both drop-down-menus or skip-links, it will work. If you are using an XHTML theme, this script will not work.

Want to see it in action? Check out the demo site. This work is thanks in large part to the efforts of the following: Rian Rieltveld, Gary Jones, Brad Potter, and Marcy Diaz. Thank you all!

Reader Interactions


  1. Hans Schuijff says

    Hi Robin,
    Thank you for again a great explanatory article, and sharing your work. I’ve been using the genesis accessibility plugin for some time now, but hadn’t orientated yet on the changes in genesis version 2.2. I’m glad I can follow your example here and have read the article of Brian too, and it seems there is a lot to think of when wanting to be fully accessible.

    I have no idea of how much people visit websites using devices that need this functionality. In my stats I’ve never noticed it. But it’s a nice, and welcoming, idea to be prepared for their visit.

    In my own websites, at the moment using standard Studiopress child themes (Enterprise Pro and Modern Studio Pro) I’ve noticed that the submenu’s are not shown when I tab-through the option with my keyboard, so I might have some work to do. Most of the time Studiopress child themes seem rather basic in their responsive menu’s so I will like to try the menu you describe. Perhaps only changing the colors and changing the responsive menu-icon to a x when the menu is open (indicating it can be closed). Both will probably just need some small css changes, so it’s nice and thanks.

    Looking at your demo-site it seems to function flawlessly when using the tab-key to navigate through the options. Going back using shift+tab also works, but then submenu-levels are skipped, so that doesn’t work perfectly. I guess that might be more work than it would be worth?

    You also speak of your menu-plugin. You there choose for a responsive menu that doesn’t fill the entire screen wide. I’m curious if there are functional reasons for one or the other way. Is it just a design preference? Or are there some technical of functional advances of that method?

    Keep on the great work. My thanks to you all, that contributed to this solution.

    Kind regards, Hans

    • Robin says

      Hmmm, I’ll have to look into the buttons being skipped if you go backwards; thanks for mentioning that!

      Yes, the buttons have a unique class added if the submenu following is open, so you could easily change the icon to an X, or anything you like, to visually show a different state.

      No, SuperSide Me does not fill the entire screen. I’ve seen that technique more often lately, and it could certainly be done, probably with just some CSS.

      Thank you!

  2. Angie Vale says

    thank you so much for this,
    I love your SuperSide plugin but it is good to be able to use a “native” Genesis mobile menu sometimes.

  3. MJ says

    Thanks for your tutorial – I’m trying to implement it into my site and I’m running into some issue – would love to hear your thoughts.

    Since you’re adding the menu-toggle button before the nav element, I’m running into problems when I set the e.g. nav-primary to fixed on scroll – do you see an easy work-around?


    • Robin says

      If you’re implementing a sticky nav using JavaScript, you would need to add the new primary nav menu toggle button to the array of elements which get a sticky/fixed class added on scroll. Then you would need to work on the CSS somewhat to make sure the menu shows in the right place when it opens, because it will probably want to overlay the button, which is awkward. It should, however, be manageable with some JavaScript and some CSS, as long as you are willing to experiment somewhat.

      • mj says

        Thanks for replying
        Do you see any negatives if I would add the menu-toggle button to the e.g. nav-primary container instead of adding it before? That way the nav-primary container could easily positioned fixed at the top of the screen incl. the .menu-toggle button or do I miss something here?

        Thanks again

        • Robin says

          This is actually something we experimented with and it gets fairly hairy if your theme is set up for accessibility. There are also CSS issues which have to be dealt with, since the nav container is set to disappear on smaller screens, so you would have to finagle how things work with what is hidden and what is displayed. And if your theme uses skip links at all, it gets really messy, because of what’s hidden and what’s targeted. Placing the button outside the nav container made the styling easier to manage and the skip links a whole lot easier to modify.

          • MJ says

            Thanks again
            I had another idea – how about wrapping the nav-primary and .menu-toggle and position that parent container fixed in order to get sticky navigation – would that lead into the same issues as you have described before?

          • Robin says

            Yes, it would, although the issues would be different. I’m not sure if the accessibility issues would change, or just be different. The CSS might be easier to wrangle, but I wouldn’t know without playing around with it myself. If you try it, though, let me/us know how it works!

          • MJ says

            Thanks again for replying

            actually wrapping the menu-toggle as well as the nav works like a charm – however I don’t know how it affects the screen reader stuff but I’m not much worried about that either.

            Thank again for your input.

  4. Tony says

    Thanks Robin…this was driving me crazy on a new project. I didn’t realize the new Genesis accessibility changes were causing this issue until I came across your article!

  5. Rick says

    Hey Robin,
    How is the word “menu” being added to the hamburger menu? I’ve added your code and the word does not display for me. Everything seems to be functioning properly, yet I cannot get the word “menu” to appear.

    • Robin says

      Menu is being added in the functions file, where the js is enqueued. The variables are set in PHP and then localized for the js to use (wp_localize_script).

  6. Dave Turnbull says

    Fantastic work!

    I’m building a site for a blind and low vision education network, which will utalise BuddyPress for community features. I’d like to use the secondary Genesis menu as the ‘Community menu’, and the primary Genesis menu as the ‘Main menu’.

    Currently, when viewed at mobile breakpoint, both menus are collapsed to a single ‘Menu’ item—that is both menus read ‘Menu’, before they’re expanded/toggled.

    Can you please tell me how I can change the name of each menu independently, so that a sighted person will see ‘Community menu’ and ‘Main menu’, and a screen reader will also be aware of the difference?

    Thanks very much!

    • Robin says

      Hey Dave! That’s a great question, although the answer is a bit complicated. Your first step would be to add a new variable into the array which is localized in the functions.php. Then you would need to create a new button in the js, and probably duplicate the $( 'nav' ).before( ); // add the main nav buttons line so that you can make it specific to each menu.

      Another option would be to combine the main and community menus on mobile devices, so that there is only one button and one menu, which is another level of complexity. I haven’t looked closely at it, but I think the Workstation Pro mobile menu may combine the two menus; I am not sure how it handles the skip link navigation.

      • Dave Turnbull says

        Thanks so much Robin!

        I’ll pass your helpful advice on to someone who can help me make the edits and test it out. Much appreciated!

        If and when I get this working, I’ll post the edits back here for others to make use of them.


      • Dave Turnbull says

        Hi again Robin

        I’ve not been able to find a JS developer to help me with the changes you suggested (in order to give the secondary menu a different name, when collapsed to mobile). I’ve tried myself to make the edits, though I’ve not had much success! In fact quite the opposite! 🙂 I think it’s mostly in the “addition of the button in the JS and duplicating the main nav line” where I come unstuck.

        e.g. re: the array in the functions.php—I assume the edit is from:

        $output = array(
        ‘mainMenu’ => __( ‘Main menu’, ‘leaven’ ),
        ‘subMenu’ => __( ‘Menu’, ‘leaven’ ),


        $output = array(
        ‘mainMenu’ => __( ‘Main menu’, ‘leaven’ ),
        ‘mainMenuSecondary’ => __( ‘Community menu’, ‘leaven’ ),
        ‘subMenu’ => __( ‘Menu’, ‘leaven’ ),

        But as far as adding a button in the JS, well, I’ve had some rather unexpected results! It’s been fun.

        Is there any way I could ask you to provide a more detailed explanation, so I can give it another crack?

        Sorry to be a bother!

        • Robin says

          There are several moving parts involved, so yes, it is a bit tricky. My first guess would be to duplicate the section where the menu toggle button is being defined, and replace the mainMenu with subMenu. Then this line needs to be duplicated and made specific to each menu:

          $( 'nav' ).before( ); // add the main nav buttons

          I think that should get you fairly well on your way. However, not to be self serving, but might I suggest that you consider using SuperSide Me instead? I’ve worked hard to make it accessible, and it will automatically combine both menus into a single menu panel. In the end, it would be less time (and money, likely) than trying to build it out by hand.

  7. James says

    Hi Robin, First of all thank you so much for this tutorial. I have been struggling with my mobile menu for a long time and this is the first reasonable solution of found. However, after I went through the tutorial I still have a couple issues I’m hoping you can help me with.

    One issue is that the icon shows up no matter what screen size. I know this is probably a simple CSS issue, but I am self-taught and am struggling to find the right code to fix. Secondly, the icon is not centered. Instead, it floats off to the left. It also has created a bit of a UX problem in that when you hover over the menu and submenu options they animate and jump up and down creating a very frustrating issue for anyone using a mouse.

    Another issue that goes along with the centering issue is I’m not getting a straight-line bar like your test site. Instead, it’s just the one button that expands out. And when it expands out you get the same animation issue on the submenus.

    Lastly, it looks like the solution did something to the responsiveness of my site. It’s awesome in that you don’t feel stuck with a tiny window of text like I was struggling with before finding your post. But all of the pages are expanded out so far you’ve got to pinch and scroll to see what you want.

    Sorry to throw this all at you, but I know I’m doing it wrong and I’m hoping you can help.

    Thank you!


    • James says

      Forgot to mention, my landscape view on mobile is aaall messed up now too… Thanks for any help you can offer!

      • Robin says

        I would remove the CSS you added from the tutorial and start that part over again. I did a quick look at your stylesheet and it looks like you’ve added everything from here into one spot inside of a media query. So the toggle buttons are set to both display none and also to display, but only at a smaller screen size, so they’re defaulting to displaying on larger screens. I’m suspicious that there is also something going on in your 1023 media query that’s messing things up, maybe an extra closing bracket, or a missing one, but can’t tell for sure. But get the initial toggle hiding out of the media query (put it before it) and that will begin to help.

  8. Shelly says

    I was able to install this menu almost flawlessly with the exception that when you first visit the site on mobile, the menu is fully extended and to close it you have to click the = bar. How can I change this to be the opposite? I would like it closed by default and expand when clicked on? Also, where can I add the word “Menu” so that it shows next to the = icon?

    Thanks so much for this great tutorial and your assistance.

    • Robin says

      Hey Shelly! It sounds like there might be something missing. The Menu text is added with the $output variable in your functions.php file, and the way the code is set up, the menu should not work at all if it isn’t set. So there may be another menu/script at work here. It should also be closed by default, as the slide/toggle action should only happen when the menu button is clicked. If you want to share a link to the site where you’re working on it, it may be easier to diagnose.

      • Shelly says

        Very strange, if you look at the domain in my email address this is where the problem is occurring. I appreciate your help. The menu looks great, otherwise.

        • Robin says

          OK, it looks like the bootstrap normalize CSS is overriding your stylesheet, for some reason. If you change this (from the tutorial):

          nav {
          display: none;
          position: relative;

          to be slightly more specific, like this:
          nav.nav-primary {
          display: none;
          position: relative;

          then I think it will work for you. Hope that helps–

          • Shelly says

            Fantastic, after clearing my cache, that seemed to do the trick. Thanks so much!!

  9. Brandon says

    It doesn’t appear to be working…I am using the Genesis Sample Theme. Does it matter that I’m using the Custom Menu in the Header Right Widget?

    • Robin says

      It should not matter, since Genesis modifies menus places in the Header Right Widget to match the standard nav markup. I just tested this locally with Genesis Sample and a menu in the Header Right area, and it worked, although the styling would need to be adjusted somewhat. Also, if you have accessibility enabled and are using a custom menu in that location, you need to add in your own skip links for it.

  10. Dave says

    Awesome tutorial Robin. Thank you for your hard work with this. ps you probably know already, but this same code was used in Atmosphere Pro 🙂

    • Robin says

      Thanks, Dave! Yes, we contacted StudioPress to share this code and asked them to look into it. It’s exciting to see parts of it in the new themes!

  11. Sean Nelson says

    I’m using a custom menu in the header right position. The menu was displaying open when loading the page. I tried the following change:

    nav {
    display: none;
    position: relative;
    nav.nav-primary {
    display: none;
    position: relative;

    but did not work. I then changed it to:
    nav.nav-header {
    display: none;
    position: relative;
    and it works fine.

    I had to set a font color for .sub-menu-toggle:before because it was white and my background was white. For a while did not realize anything was there for the drop down, until I saw code there in firebug.

    Finally (if anyone’s interested) I did not want the word “Menu” next to sub-menu icon and found it in the functions code.
    $output = array(
    ‘mainMenu’ => __( ‘Menu’, ‘leaven’ ),
    ‘subMenu’ => __( ”, ‘leaven’ ),
    I simply removed it and icon justifies right. Thanks. Great option. Looking forward to trying simpleside plugin on my own site.

  12. abby @ thingsforboys says

    Thanks for this. I have implemented it, but in mobile view I am getting 2 menus. The first one doesn’t do anything, but the second one is functional. I am only utilising the secondary nav menu and have also tweaked it to show the search bar on the right hand side of the secondary nav menu. Can you please let me know why i am getting the ‘menu’ twice in mobile view?

    • Robin says

      That’s really odd, Abby–I can’t tell why from here, but it does look like the script is adding a second button. Due to your site configuration, I can’t see your script file(s), so am unable to make any guesses as to why–sorry! Did you make any modifications to the script, and/or are there any other files which might be duplicating the work this should be doing?

      • abby @ thingsforboys says

        Thanks for your reply. There was already a responsive.js file in there, so I added your code to the end of the file. This is what was in it originally :
        jQuery(function( $ ){
        $(“.nav-primary .genesis-nav-menu”).addClass(“responsive-menu”).before(”);
        $(“.nav-primary .genesis-nav-menu”).slideToggle();
        if(window.innerWidth > 768) {
        $(“.nav-primary .genesis-nav-menu”).removeAttr(“style”);

        I tried removing that code (leaving only yours), but it didn’t help. I think I’ve updated my config so you can view the files. Any help would be appreciated. I’m making it up as I go 😉

        • Robin says

          OK, that’s fine to add this code to that file, but you need to remove what was there initially. Try that and see if it resolves the issue.

          • Robin says

            Unfortunately, with the caching, it is impossible to diagnose what might be going on (although it may actually be the cache itself needing to be flushed to use your updated code, if you haven’t already done that).

  13. Sarah says

    Thank you very much for your work, Robin. It works great with main menu and sub menu. Only the button text of the secondary menu is always the one of the main menu, it ignores the button text given to subMenu on functions.php. Do you have an Idea?
    Best solution would be to have only one menu, so main menu and sub menu items would be included into main menu on mobile screen.

    • Robin says

      Hey Sarah! The subMenu text in the functions file is actually for any dropdown menus within a menu–not for a secondary menu (it’s hidden with a screen reader text class, there more for accessibility purposes). This script processes all of the menus in the same way, so if you want to treat a secondary navigation differently, you need to separate it out within the script.

      I agree with you about wanting just one menu on a mobile screen, which is why I generally use SuperSide Me on sites with multiple menus (not to be self serving, but truthful). StudioPress used a modified version of this script in Workstation Pro (and probably the themes released since then as well), and I believe that they added the secondary menu to the primary as part of the script. I haven’t used the theme myself yet, though, so can’t say for sure.

  14. Jason says

    Absolutely awesome and worked flawlessly for me out of the gate. Thanks for the huge time-saver! Cheers.

  15. Tom says

    Hi Robin, thanks for the fantastic, hard work you’ve done to bring us this menu. I’ve implemented the menu just fine, just got a little issue. I’m displaying a logo on the nav-bar that I move to white space above the menu once your code kicks in. However when the menu toggles it pushes all the content down including my logo. I’m trying to get the logo to remain above the nav menu and I’m positioning the logo with (.site-title a img). I’m quite new to this so I apologize if the answer is obvious. Any help would be much appreciated.

    • Robin says

      Hey Tom! Sorry, without seeing the site and being able to inspect it visually, it’s hard to know specifically what you’re dealing with. My guess, however, is that it’s just CSS at this point, something maybe is set to position: relative; maybe and you’d prefer it to be absolute. Best bet is to use Chrome’s Dev Tools or Firebug and experiment with some things, but the positioning is what I would try first.

  16. Leah says

    Your Responsive Nav scripts worked perfectly, after changing “nav {” to “nav.nav-primary {” in the css as suggested in a previous comment reply.

    Thank you for saving me hours of work!

  17. Trevor says

    Hi Robin,

    Thanks for this tutorial! It works flawlessly. I have a question about adjusting the functionality – I’m working on a website where a number of the navigation links go to anchors on the home page and I’m wondering if there’s a way to modify the script so that the menu closes after the user clicks on a link?

    Thanks for any advice.

    • Robin says

      I think it’s possible, although it would take some exploring. You should be able to find the relevant menu items with something like var orphan = $( '.genesis-nav-menu .menu-item-has-children > a[href="#"]' );, and then have the script do whatever it needs to in order to close the menu when something that matches it is clicked. You can look at the _maybeClose function for ideas of what needs to happen when the menu is closed. Hope that helps you get started!

  18. Josh says

    What a great tutorial and it works perfectly and natively!

    I’m just trying now to make the the responsive menu only apply to my top widget menu (which it does and it works great), but I don’t want my primary navigation menu to be responsive. Would you have any idea how I might go about excluding the primary navigation from being responsive?

    Thanks, Josh

    • Robin says

      The navigation buttons are added to every nav element in line 28 of the js. You can change that line to be more specific and target only your custom menu in the widget. You’ll probably need to go through and revise the CSS as well, since all navigation menus will be hidden, so you’ll want to make it more specific. Hope that helps!

  19. Ciprian says

    Thank you very much, Robin – this tutorial helped me a lot!

  20. Byoung Lee says

    Hi Robin,

    Thank you for the fabulous tip! I’ve implemented the codes according to your instructions, but I’ve ran into a slight issue. My client does not need the submenu. How would I go about changing the code so that only the main menu is displayed?

    Thanks in advance!

    • Robin says

      If you’re meaning the secondary navigation, check this comment, which discusses how to target specific navigation menus. If you want just the top level menu items, I think that might require some more intensive work, either with the js or CSS, and it would take some fiddling to accomplish.

  21. Pauline says

    Hi Robin,

    I don’t understand why, but my menu-toggle button doesn’t appear. I have develop my website in local and the responsive menu works good, but now it is online, I have this issue…
    The menu-toggle button will be in html code, but when I inspect the code, it’s not here. I really don’t know why…

    If you could help me, it will be fantastic!

    • Robin says

      Hey Pauline! I went to the link in your comment profile and do not see any theme javascript loading that would activate the responsive menu and reveal it, although it appears that the styling is set up. You may need to double check your enqueue methods and see why they’re not loading your script(s).

  22. markdeafmcguire says


    I wanted to take the time to thank you for posting this. I find it fits my needs perfectly. I do have one nagging issue I am currently troubleshooting. I am not sure what is causing it.

    My main menu has 4 pages, home, about, blog, more information.

    When the screen is resized to a point where the responsive menu kicks in, for some reason, home is stuck behind the “menu” when the dropdown is activated. The other three pages shows up.

    I suspect this is due to a css code, maybe a padding or margin or position issue? I do have the nav menu fixed for the purpose of easier access to navigate. Could this be what’s affecting the responsive position of the first page on the menu?

    You might be able to see what I mean on my site. I hope it’s just not me imagining things here.

    I’m not exactly sure because I’m on an accessible learning curve. 🙂 You have been producing excellent tutorials for me. As a deaf person, accessibility is important to me and I really appreciate you leading the way along with others who love the Genesis framework.

    • Robin says

      Hey Mark! Thanks so much for your kind words–I really appreciate it!

      You are right that the fixed position is what’s giving you the placement issue, but I think it’s a pretty easy fix, once you know where to look. Try adding this to your media query section (I think the one that starts at line 1129 of your stylesheet):

      nav.nav-primary {
      top: 63px;

      I think you can adjust the number however you like, but that seemed to be enough to not show behind the button.

      Another option would be to set that selector to be relatively positioned instead of fixed (on small screens only), but that will push the site down when you press the button, rather than the menu sliding down over the site.

      • markdeafmcguire says

        Okay, I tried the top: solution and it didn’t work. I changed all the fixed back to relative and it does work, it doesn’t keep the menu fixed so I’m going to investigate this further.

        It does look smoother though. I thought about adding those “scroll up” button overlay but I don’t know if those are accessible.

  23. Carrie says

    Thank you so much for this tutorial! The comments section helped me troubleshoot my issue and it’s working perfectly for me now 🙂

  24. david says

    I’ve noticed in your demo (and my implementation) that, if your menu has too many items and the menu expands to be taller than your viewable area, there’s no way to scroll down and select the last few menu options. Any way to fix this?

    • Robin says

      For longer/more complex menus, this is not the solution I would choose. I confess I have not given thought to how to deal with it in this context.

  25. Amy says

    Hi, this worked great for me! However I tested my site on a mobile device and for some reason when the menu toggles down, my site content is visible behind the menu and the last two links won’t work. URL is I’d appreciate anyone’s help, I am a BEGINNER developer and ultra beginner for wordpress. lol thanks!

    • Robin says

      You have a height of 80px set on .genesis-nav-menu, which is causing that. You should remove that and then adjust the padding on .genesis-nav-menu a, which is currently a kind of wonky mix of numbers–but you can even them out and get the same visual appearance without locking the menu height in the way it currently is.

  26. Atul says

    Nice tutorial bro, it is working as expected. I tried same with many of my clients site who wanted a different design of menu. Many thanks.

  27. Lord says

    Thank you for this! Really helpful.

    This is probably very easy to do but how do I make the menus closed/not expanded by default? Can’t seem to find the code!


    • Robin says

      The menus should be closed by default–you may have a script conflict or CSS making them expand.

  28. Stephanie says

    Dear Robin,
    my question probably a stupid one, but i don´t have any idea about code 😉
    Where exactly would i enter this code? Just at the end of the css/php?
    I am afraid of messing up the php..

    • Robin says

      Each gist/block of code has a file name–you can probably add that code to the matching file in your theme (functions.php, style.css, but most likely you will have to create the javascript file). Definitely be careful: practice safe coding, make sure your site/files are backed up, and I would recommend not using the WP theme editor to edit files.

  29. Paul says

    Looking to give this a try as I am not happy with the default menu of the executive pro theme v3.0.0 as it has no toggle menu for mobile devices.

    Quick question before I start: Because I am a relative newbie to php and genesis themes, how do I determine whether I have the skip links feature in my child theme?

    I’ve looked through the functions.php in executive pro but don’t see any reference to skip links. Does this mean I don’t have to add the first code of the tutorial in my functions.php file?

    Sorry for the dumb question but just wanted to make sure I don’t mess anything up.

    • Robin says

      No worries, that’s an excellent question! The skip links will be added if the theme adds support for genesis accessibility. You’ll want to look for a line that starts with something like this:

      add_theme_support( 'genesis-accessibility', ...

      There will be an array for the next part. If skip-links is in the array, your theme has them–if not, then likely it doesn’t.

  30. DragonLee says

    Thank you so very much for posting this article. I was upgrading an old Genesis site that had been hacked to the newest Genesis and was appalled that the mobile menus did not work correctly. After spending too much time trying to figure it out, I found your tutorial. Now the site works perfectly across all media. Thanks!

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.