Skip to content

Embed URL

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
WordPress Menu & Walker for ZURB's Foundation 4 Top Bar

Adding a Foundation Top Bar to WordPress

foundation-topbar-menu.php and foundation-topbar-walker.php should be required in the WordPress functions.php file.

The code in foundation-topbar.php should be added below the body tag in header.php

Setup a menu in WordPress admin under Appearance > Menus

Use the 'label' class on a menu item to create a menu section title

Foundation Top Bar Doc: http://foundation.zurb.com/docs/components/top-bar.html

<?php
add_theme_support('menus');
/**
* Register Menus
* http://codex.wordpress.org/Function_Reference/register_nav_menus#Examples
*/
register_nav_menus(array(
'top-bar-l' => 'Left Top Bar', // registers the menu in the WordPress admin menu editor
'top-bar-r' => 'Right Top Bar'
));
/**
* Left top bar
* http://codex.wordpress.org/Function_Reference/wp_nav_menu
*/
function foundation_top_bar_l() {
wp_nav_menu(array(
'container' => false, // remove nav container
'container_class' => '', // class of container
'menu' => '', // menu name
'menu_class' => 'top-bar-menu left', // adding custom nav class
'theme_location' => 'top-bar-l', // where it's located in the theme
'before' => '', // before each link <a>
'after' => '', // after each link </a>
'link_before' => '', // before each link text
'link_after' => '', // after each link text
'depth' => 5, // limit the depth of the nav
'fallback_cb' => false, // fallback function (see below)
'walker' => new top_bar_walker()
));
}
/**
* Right top bar
*/
function foundation_top_bar_r() {
wp_nav_menu(array(
'container' => false, // remove nav container
'container_class' => '', // class of container
'menu' => '', // menu name
'menu_class' => 'top-bar-menu right', // adding custom nav class
'theme_location' => 'top-bar-r', // where it's located in the theme
'before' => '', // before each link <a>
'after' => '', // after each link </a>
'link_before' => '', // before each link text
'link_after' => '', // after each link text
'depth' => 5, // limit the depth of the nav
'fallback_cb' => false, // fallback function (see below)
'walker' => new top_bar_walker()
));
}
?>
<?php
/**
* Customize the output of menus for Foundation top bar
*/
class top_bar_walker extends Walker_Nav_Menu {
function display_element( $element, &$children_elements, $max_depth, $depth=0, $args, &$output ) {
$element->has_children = !empty( $children_elements[$element->ID] );
$element->classes[] = ( $element->current || $element->current_item_ancestor ) ? 'active' : '';
$element->classes[] = ( $element->has_children ) ? 'has-dropdown' : '';
parent::display_element( $element, $children_elements, $max_depth, $depth, $args, $output );
}
function start_el( &$output, $object, $depth = 0, $args = array(), $current_object_id = 0 ) {
$item_html = '';
parent::start_el( $item_html, $object, $depth, $args );
$output .= ( $depth == 0 ) ? '<li class="divider"></li>' : '';
$classes = empty( $object->classes ) ? array() : (array) $object->classes;
if( in_array('label', $classes) ) {
$output .= '<li class="divider"></li>';
$item_html = preg_replace( '/<a[^>]*>(.*)<\/a>/iU', '<label>$1</label>', $item_html );
}
if ( in_array('divider', $classes) ) {
$item_html = preg_replace( '/<a[^>]*>( .* )<\/a>/iU', '', $item_html );
}
$output .= $item_html;
}
function start_lvl( &$output, $depth = 0, $args = array() ) {
$output .= "\n<ul class=\"sub-menu dropdown\">\n";
}
}
?>
<div class="top-bar-container fixed contain-to-grid">
<nav class="top-bar">
<ul class="title-area">
<li class="name">
<h1><a href="<?php echo home_url(); ?>"><?php bloginfo('name'); ?></a></h1>
</li>
<li class="toggle-topbar menu-icon"><a href="#"><span>Menu</span></a></li>
</ul>
<section class="top-bar-section">
<?php foundation_top_bar_l(); ?>
<?php foundation_top_bar_r(); ?>
</section>
</nav>
</div>
@xarem

Great - you're my hero! Thank you very much!

@awshout
Owner

GitHub should really notify me of comments on gists! That's not nice of them.

You're welcome! I'm glad this has been helpful to others.

@tiasch

"As of PHP 5.3.0, you will get a warning saying that "call-time pass-by-reference" is deprecated when you use & in foo(&$a);. And as of PHP 5.4.0, call-time pass-by-reference was removed, so using it will raise a fatal error. "
Quote form from http://php.net/manual/en/language.references.pass.php

in "foundation-topbar-walker.php" on line 13, it should probably be changed from:

parent::display_element($element, &$children_elements, $max_depth, $depth, $args, &$output);

to

parent::display_element($element, $children_elements, $max_depth, $depth, $args, $output);

By doing that I could get rid of the fatal error as I'm using PHP 5.4.4
Does that sound correct?

Thanks for the Snippet awshout!

@awshout
Owner

You're absolutely right. Thanks for catching that!

@Phlow

Great. You helped me a lot. Now, I just have to get a search form into the right menu by default :)

@awshout
Owner

Glad to help.

For the search form... It will take a bit more work, but to get you started you could use the following in the <section> tag:

<ul class="right"><li><?php get_search_form(); ?></li></ul>
@italiafirenze

I just spent a day hacking around with Reverie to get this to work. Then I find this :-(

Great work though, thanks.

@juandelperal

Awesome!
Thanks!

@ShayHurley

Thanks, just found this and put it to use straight away !!!

@awshout
Owner

You're welcome. I'm happy to see so many using it.

@amrinz

Thanks awshout, its work well in my theme.

but I dont know why, when i see in responsive layout using web developer, the toggle menu did not work :-)

can you tell me any possibility why this is not work. also what css should i use for content bellow top-bar not-covered by top-bar ?

thanks for your help

@awshout
Owner

Hi @amrinz, it's possible that there is a jQuery conflict.

I'm not sure what you're asking for about the CSS. Follow the grid outline provided by ZURB for any content below the top bar.

@prescottt

Nice one updating this to work with foundation 4, cheers.

@tiasch

Was it updated to work with foundation 4?

@awshout
Owner

The last two revisions should have updated it to F4. Let me know if I missed anything though.

@JakeSnake

Hey Awshout,
I would like to thank you for this, very awesome that you shared it! Great work, keep it up!

@MrShores

Thank you very much!

@awshout
Owner

You're welcome!

@dafLands

Thank you sir, you rock!

@iggmack

Thanks for this! But how to incluce the menu item description into the mix?

@awshout
Owner

@iggmack the top bar isn't really setup to hold the description without some CSS work. To add it into the Walker you'd do something like this in start_el:

if ( !empty( $item->description ) ) {
    $item_html .= '<span class="description">' . esc_attr( $item->description ) . '</span>';
}
@nithino

Thank you. You saved my day. Bookmarking it!

@iggmack

Thanks!

@MIKendall

Just updated to WordPress 3.6 and got a Strict error regarding start_el: the fix I made is:

function start_el( &$output, $object, $depth = 0, $args = array(), $current_object_id = 0 ) {

    $item_html = '';
    parent::start_el($item_html, $object, $depth, $args);

    $output .= ($depth == 0) ? '<li class="divider"></li>' : '';

    $classes = empty($object->classes) ? array() : (array) $object->classes;

    if(in_array('label', $classes)) {
        $output .= '<li class="divider"></li>';
        $item_html = preg_replace('/<a[^>]*>(.*)<\/a>/iU', '<label>$1</label>', $item_html);
    }

if ( in_array('divider', $classes) ) {
    $item_html = preg_replace( '/<a[^>]*>( .* )<\/a>/iU', '', $item_html );
}

    $output .= $item_html;
}
@juliosampaio

To get a search form into the right menu by default:


// the right top bar
function foundation_top_bar_r() {
    $menu = wp_nav_menu(array( 
        'echo' => false,
        'container' => false,                           // remove nav container
        'container_class' => '',                // class of container
        'menu' => '',                               // menu name
        'menu_class' => 'top-bar-menu right',           // adding custom nav class
        'theme_location' => 'top-bar-r',                // where it's located in the theme
        'before' => '',                                 // before each link <a> 
        'after' => '',                                  // after each link </a>
        'link_before' => '',                            // before each link text
        'link_after' => '',                             // after each link text
        'depth' => 5,                                   // limit the depth of the nav
        'fallback_cb' => false,                         // fallback function (see below)
        'walker' => new top_bar_walker()
    ));    
     add_search_form($menu); //new function (bellow)
} // end right top bar


function add_search_form($topBar){
    //get the menu and create a php DOMDocument
    $dom = new DOMDocument();
    $dom->loadXML($topBar);
    $xpath = new DOMXPath($dom);
    //get the ul
    $res = $xpath->query("/ul")->item(0);
    //call your search form (notice the false arg)
    $form = get_search_form(false);
    //create a new li tag
    $li_search = $dom->createElement("li");
    //append the search form to a new dom fragment
    $form_html = $dom->createDocumentFragment();    
    $form_html->appendXML($form);    
    $li_search->appendChild($form_html);
    //create de F4 has-form css class and add it to our $li_search
    $class = $dom->createAttribute("class");
    $class->value = "has-form";    
    $li_search->appendChild($class);
    //create a divider li
    $li_divider = $dom->createElement("li");
    $li_divider_class = $dom->createAttribute("class");
    $li_divider_class->value = "divider hide-for-large hide-for-medium";
    $li_divider->appendChild($li_divider_class);
    //more appends
    $res->appendChild($li_divider);
    $res->appendChild($li_search);
    //return our topbar with a search form
    echo $dom->saveXML($res);
}

@awshout
Owner

Thanks for the update @MIKendall

@juliosampaio That's some nice work there. However, I would probably just create a function to output the form for a search input.

function top_bar_search() {

    $output  = '<ul class="right"><li class="has-form">';
    $output .= '<form role="search" method="get" id="searchform" action="' . home_url() . '"><div class="row collapse">';
    $output .= '<div class="large-8 small-8 columns">';
    $output .= '<input type="text" value="' . get_search_query() . '" name="s" id="s" placeholder="' . esc_attr__('Search', 'reactor') . '" />';
    $output .= '</div>';
    $output .= '<div class="large-4 small-4 end columns">';
    $output .= '<input class="button prefix" type="submit" id="searchsubmit" value="' . esc_attr__('Search', 'reactor') . '" />';
    $output .= '</div>';
    $output .= '</div></form>'; 
    $output .= '</li></ul>';

    return $output;
}
@phil2508

Would you have any clue why the walker does not get any sub categories? I'm looking at

element->has_children = !empty( $children_elements[$element->ID] );

and it is always empty, although the category clearly has sub categories.

What is going on?

Thanks!

@edequalsawesome

You just saved my sanity. Thanks!

@vajaah

Was about to write a walker class for this and then voila! Thanks!

@shariffrb

no dropdown in foundation 4.3.1

@davejwilliams

Dropdowns aren't working for me either. :(

@chris-roerig

To fix the drop down issue, add "not-click" class to the "has-dropdown" line.

class top_bar_walker extends Walker_Nav_Menu {

function display_element( $element, &$children_elements, $max_depth, $depth=0, $args, &$output ) {
    $element->has_children = !empty( $children_elements[$element->ID] );
    $element->classes[] = ( $element->current || $element->current_item_ancestor ) ? 'active' : '';
    $element->classes[] = ( $element->has_children ) ? 'has-dropdown not-click' : '';

    parent::display_element( $element, $children_elements, $max_depth, $depth, $args, $output );
}

....
@genuino2

This is the WALKER code with all fix


class top_bar_walker extends Walker_Nav_Menu {
    function display_element( $element, &$children_elements, $max_depth, $depth=0, $args, &$output ) {
        $element->has_children = !empty( $children_elements[$element->ID] );
        $element->classes[] = ( $element->current || $element->current_item_ancestor ) ? 'active' : '';
        $element->classes[] = ( $element->has_children ) ? 'has-dropdown not-click' : '';
    
        parent::display_element( $element, $children_elements, $max_depth, $depth, $args, $output );
    }

    function start_el( &$output, $object, $depth = 0, $args = array(), $current_object_id = 0 ) {
    
        $item_html = '';
        parent::start_el($item_html, $object, $depth, $args);
    
        $output .= ($depth == 0) ? '
  • ' : ''; $classes = empty($object->classes) ? array() : (array) $object->classes; if(in_array('label', $classes)) { $output .= '
  • '; $item_html = preg_replace('/]*>(.*)<\/a>/iU', '$1', $item_html); } if ( in_array('divider', $classes) ) { $item_html = preg_replace( '/]*>( .* )<\/a>/iU', '', $item_html ); } $output .= $item_html; } function start_lvl( &$output, $depth = 0, $args = array() ) { $output .= "\n
    • \n"; } }
    @holisticnetworking

    "Notice: Indirect modification of overloaded property WP_Post::$classes has no effect in ../functions.php on line 566"
    "Notice: Trying to get property of non-object in .../wp-includes/nav-menu-template.php on line 88"

    Any guesses? WordPress 3.5.2

    @holisticnetworking

    This hack fixed the above problem for me, though for some reason, I still can't get the menus to display correctly:

    $element->has_children = !empty($children_elements[$element->ID]);
    $classes = $element->classes;
    $classes[] = ($element->current || $element->current_item_ancestor) ? 'active' : '';
    $classes[] = ($element->has_children) ? 'has-dropdown' : '';
    $element->classes = $classes;

    @TRWebDesign

    The "not-click" class is added by foundation.topbar.js on-the-fly when the menu is in "hover" mode. If you're not seeing the "not-click" class applied to your parent li's at runtime, then maybe check for jQuery conflict like the author said or any other errors in your console. Might save more aggravation later..

    @daniel7912

    Thanks a lot for this, exactly what I was looking for. Saved me loads of time!

    @rffaguiar

    Just as I thought! I was trying to make it work and I thought "someone in the world must have solved this already".
    Put this star at your code.

    @fertchen

    Thanks a lot for sharing this. But...I just can't get this to work. Granted, I don't know a lot about these things. I have done as you advised, included the files, added the script as advised at http://foundation.zurb.com/docs/components/top-bar.html, added the CSS and the menu bar does indeed appear.
    It also turns into the mobile menu when I decrease the browser width (Chrome).

    But upon clicking on the menu, it does not drop down (I did use the code with the fixes by . How can I troubleshoot this?

    I am using this for a Wordpress installtion with a Twenty Twelve Child Theme.

    @jeltoesolnce

    Thank you.

    @pulla

    is there any update for foundation 5? it's not working with foundation 5 now.
    Thanks :)

    @pulla

    oops just found data-topbar .. it works great

    @thanhrossi

    Not working with Foundation 5? hicc :?

    @PaoloVIP

    Works for me with foundation 5 and Wordpress 3.7.1.
    For drop down I added "not-click" like 808chris suggested. Works fine. Thank you

    @StefsterNYC

    Ah this is awesome. I'm so close. Nothing showing up though. Using F5 but so far no luck. What am I missing?
    1. Both .php files are in a inc folder.
    2. Markup in header
    3. Calling both php from functions file.

    Did I miss something?

    @StefsterNYC

    Ah! I got it working. Awesome.

    @maddtechwf

    I'm using F5 also. I have the navigation working but when it gets to a smart phone screen it doesn't work for some reason. Any ideas why?

    ** I FOUND THE FIX. If you downloaded Foundation 5.0.0 then you will have issues. If you download 5.0.1 or 5.0.2 it will fix it for you.

    @Maikenvv

    Thank you so much for this code. I've got Foundation 5.0.2. working with normal nav and mobile. I'm wondering if anyone also had a problem with the dropdown menu's. I can't get them to work. I can click on the parent, and darkens it's color, but no dropdown appears. I've already tried z-index.

    @demo38

    Sending positive vibes - because you deserve them. Thanks for taking the time to put this together - hugely useful. @awshout

    @nilocoelhojunior

    Thank you so much for this code

    @StefsterNYC

    I'm not sure if anyone commented on this so I'm just going to throw this out there. When the menu goes below 767px a parent tab that has a page attached to it and children becomes a non usable tab. You click on it and it just slides the menu over to the children rather than actually going to that page. Has anyone else experienced that and if so what was the fix to this? Thanks.

    @bei-soan

    @StefsterNYC I have this issue too, but on every size. Do you have any news about this issue already?

    @mmerriweather

    @aweshout I used the function you wrote to add a search input to the right menu, and it is not showing up in the top bar menu. I added the function inside foundation-topbar-menu.php. Was that the wrong place to add it?

    <div class="top-bar-container fixed contain-to-grid">
                <nav class="top-bar" data-topbar>
                    <ul class="title-area">
                        <li class="name">
                            <h1><a href="<?php echo home_url(); ?>"><?php bloginfo('name'); ?></a></h1>
                        </li>          
                        <li class="toggle-topbar menu-icon"><a href="#"><span>Menu</span></a></li>
                    </ul>
                    <section class="top-bar-section">
                        <?php foundation_top_bar_l(); ?>
                        <?php foundation_top_bar_r(); ?>
                        <ul class="right"><li><?php top_bar_search(); ?></li>
    
    
                    </section>
                </nav>
            </div>
    {
        // code
    }
    @jeremybutler

    Very useful and time saving, thanks for making this public!

    @flowdee

    manually added the "not-click" class which reactivated the dropdown but the mobile/responsive navigation doesn't work any more. suggestions? i click the icon but nothing happens

    @rozeykex

    @flowdee check you have this in your head,

    <meta name="viewport" content="width=device-width">
    @captaincoffee

    Can anyone point to a functioning starter theme that incorporates this? It would be very helpful to see exactly how this is implemented within the various files. Especially for us beginners. Thanks.

    @zerodburn

    Excellent!

    For the search form, or anything at the end of the menu I used this code:

    add_filter( 'wp_nav_menu_items', 'your_custom_menu_item', 10, 2 );
    function your_custom_menu_item ( $items, $args ) {
        if ($args->theme_location == 'top-bar-r') {
            $items .= '<li class="has-form">';
            $items .= '    <form role="search" class="searchform" method="get" action="' . home_url() . '">';
            $items .= '        <div>';
            $items .= '            <input id="sf-s" name="s" value="' . get_search_query() . '" type="text" onkeyup="buttonUp()" placeholder="Search..." />';
            $items .= '            <input id="sf-searchsubmit" type="submit" value="" />';
            $items .= '            <span class="search-icon-toggle" title="Click to Search"></span>';
            $items .= '        </div>';
            $items .= '    </form>';
            $items .= '</li>';
        }
        return $items;
    }
    

    (Obviously use whatever HTML you need)

    @tawshmcd

    I'm trying to add the description

    if ( !empty( $item->description ) ) {
        $item_html .= '<span class="description">' . esc_attr( $item->description ) . '</span>';
    }
    

    But I'm unsure of where to place it amongst all this:

    / CUSTOMIZE THE OUTPUT OF MENUS FOR FOUNDATION TOP BAR 
    class top_bar_walker extends Walker_Nav_Menu {
    
        function display_element( $element, &$children_elements, $max_depth, $depth=0, $args, &$output ) {
            $element->has_children = !empty( $children_elements[$element->ID] );
            $element->classes[] = ( $element->current || $element->current_item_ancestor ) ? 'active' : '';
            $element->classes[] = ( $element->has_children ) ? 'has-dropdown' : '';
    
            parent::display_element( $element, $children_elements, $max_depth, $depth, $args, $output );
        }
    
        function start_el( &$output, $object, $depth = 0, $args = array(), $current_object_id = 0 ) {
            $item_html = '';
            parent::start_el( $item_html, $object, $depth, $args ); 
    
            // $output .= ( $depth == 0 ) ? '<li class="divider"></li>' : '';
    
            $classes = empty( $object->classes ) ? array() : (array) $object->classes;  
    
            if( in_array('label', $classes) ) {
                $output .= '<li class="divider"></li>';
                $item_html = preg_replace( '/<a[^>]*>(.*)<\/a>/iU', '<label>$1</label>', $item_html );
            }
    
        if ( in_array('divider', $classes) ) {
            $item_html = preg_replace( '/<a[^>]*>( .* )<\/a>/iU', '', $item_html );
        }
    
            $output .= $item_html;
        }
    
        function start_lvl( &$output, $depth = 0, $args = array() ) {
            $output .= "\n<ul class=\"sub-menu dropdown\">\n";
        }
    
    }
    

    And also don't I have to add it to call it out in my arguments with something like this?

    'walker' => new description_walker()
    

    So far everywhere I've tested adding it, has failed.

    @Warkman

    The fix to have the dropdown work in foundation 5 (WP 4.1) is change in foundation4-topbar.php file, line 2:

    from
    <nav class="top-bar">
    to
    <nav class="top-bar" data-topbar>

    @valensiaope

    thank you for this awshout, it helped a lot!

    Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
    Something went wrong with that request. Please try again.