Skip to content

Instantly share code, notes, and snippets.

@awshout
Last active August 19, 2023 02:44
Show Gist options
  • Save awshout/3943026 to your computer and use it in GitHub Desktop.
Save awshout/3943026 to your computer and use it in GitHub Desktop.
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>
@nilocoelhojunior
Copy link

Thank you so much for this code

@StefsterNYC
Copy link

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

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

@mmerriweather
Copy link

@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
Copy link

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

@flowdee
Copy link

flowdee commented May 9, 2014

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

@rosemckeon
Copy link

@flowdee check you have this in your head,

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

@captaincoffee
Copy link

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.

@patrick-wc
Copy link

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)

@sabotawsh
Copy link

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

Warkman commented Nov 27, 2014

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>

Copy link

ghost commented Dec 30, 2014

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