Menu icon Foundation
Enabling Foundation 5 nav with WordPress menus

Does anyone have any advice for making Foundation menus play nicely with wp_nav_menu so that the beautiful styling and functionality in Foundation 5 can be used in WordPress?

navtopbarwordpress

Does anyone have any advice for making Foundation menus play nicely with wp_nav_menu so that the beautiful styling and functionality in Foundation 5 can be used in WordPress?


Courtney Ivey gave the most helpful answer for this post
Courtney Ivey over 5 years ago

Here's a Walker that we use that works pretty good with Foundation 5 so far...

Hope this helps!

/**
 * Top Bar Walker
 *
 * @since 1.0.0
 */
class Top_Bar_Walker extends Walker_Nav_Menu {
  /**
    * @see Walker_Nav_Menu::start_lvl()
   * @since 1.0.0
   *
   * @param string $output Passed by reference. Used to append additional content.
   * @param int $depth Depth of page. Used for padding.
  */
    function start_lvl( &$output, $depth = 0, $args = array() ) {
        $output .= "\n<ul class=\"sub-menu dropdown\">\n";
    }

    /**
     * @see Walker_Nav_Menu::start_el()
     * @since 1.0.0
     *
     * @param string $output Passed by reference. Used to append additional content.
     * @param object $item Menu item data object.
     * @param int $depth Depth of menu item. Used for padding.
     * @param object $args
     */

    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) ) {
            $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;
    }

  /**
     * @see Walker::display_element()
     * @since 1.0.0
   * 
   * @param object $element Data object
   * @param array $children_elements List of elements to continue traversing.
   * @param int $max_depth Max depth to traverse.
   * @param int $depth Depth of current element.
   * @param array $args
   * @param string $output Passed by reference. Used to append additional content.
   * @return null Null on failure with no changes to parameters.
   */
    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 );
    }

}

Sam Jones over 5 years ago

Hi again Andrew,

This is something I'm actively working on at the moment for a personal project of mine the only ways I could think of were either using Sass extend to apply Foundations menu style to WordPress classes or creating a custom walker which you can program to apply the required classes to links and list items.

Personally I'm looking into a custom walker. There is a skeleton theme called Roots which has a nice example of a custom walker.

Hope it helps.
Cheers
Sam

Courtney Ivey over 5 years ago

Here's a Walker that we use that works pretty good with Foundation 5 so far...

Hope this helps!

/**
 * Top Bar Walker
 *
 * @since 1.0.0
 */
class Top_Bar_Walker extends Walker_Nav_Menu {
  /**
    * @see Walker_Nav_Menu::start_lvl()
   * @since 1.0.0
   *
   * @param string $output Passed by reference. Used to append additional content.
   * @param int $depth Depth of page. Used for padding.
  */
    function start_lvl( &$output, $depth = 0, $args = array() ) {
        $output .= "\n<ul class=\"sub-menu dropdown\">\n";
    }

    /**
     * @see Walker_Nav_Menu::start_el()
     * @since 1.0.0
     *
     * @param string $output Passed by reference. Used to append additional content.
     * @param object $item Menu item data object.
     * @param int $depth Depth of menu item. Used for padding.
     * @param object $args
     */

    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) ) {
            $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;
    }

  /**
     * @see Walker::display_element()
     * @since 1.0.0
   * 
   * @param object $element Data object
   * @param array $children_elements List of elements to continue traversing.
   * @param int $max_depth Max depth to traverse.
   * @param int $depth Depth of current element.
   * @param array $args
   * @param string $output Passed by reference. Used to append additional content.
   * @return null Null on failure with no changes to parameters.
   */
    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 );
    }

}

Andrew Brown over 5 years ago

Thanks guys.

Courteny Elizabeth - where did you find that code? Is it your own and is it on GitHub? Thanks so much for sharing it.

Richard Smith over 5 years ago

Courtney, what does your code do exactly? I need to get rid of the < div > and < ul > tags for my theme and add the appropriate classes for dropdowns.

Nick Lansdell over 5 years ago

Courtney, thanks for sharing your code above it works well. How do you remove the extra classes that are generated by Wordpress for example:

"menu-item menu-item-type-post_type menu-item-object-page menu-item-has-children"

I am only interested in the Foundation code and cannot see where the extra classes are being generated.

Adam Clark over 5 years ago

Nick, you could use filters to basically pass an empty array.

add_filter('nav_menu_css_class', 'my_css_attributes_filter', 100, 1);
add_filter('nav_menu_item_id', 'my_css_attributes_filter', 100, 1);
add_filter('page_css_class', 'my_css_attributes_filter', 100, 1);
function my_css_attributes_filter($var) {
  return is_array($var) ? array() : '';
}

Garet Hindman over 5 years ago

I wrote this walker class today. It will output your menu just like foundation 5.

In functions.php add

class p2p_foundation_walker extends Walker_Nav_Menu{

  function start_el(&$output, $item, $depth, $args){

   global $wp_query;
   $indent = ( $depth ) ? str_repeat( "\t", $depth ) : '';

  $class_names = $value = '';

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

  $current_indicators = array('current-menu-item', 'current-menu-parent', 'current_page_item', 'current_page_parent');

  $newClasses = array('button');

        foreach($classes as $el){
        //add button class and check if it's indicating the current page.
                if (in_array($el, $current_indicators)){
                        array_push($newClasses, $el);
                }
        }

    $class_names = join( ' ', apply_filters( 'nav_menu_css_class', array_filter( $newClasses), $item ) );
    if($class_names!='') $class_names = ' class="'. esc_attr( $class_names ) . '"';


    $output .= $indent . '<li>';

    $attributes  = ! empty( $item->attr_title ) ? ' title="'  . esc_attr( $item->attr_title ) .'"' : '';
    $attributes .= ! empty( $item->target )     ? ' target="' . esc_attr( $item->target     ) .'"' : '';
    $attributes .= ! empty( $item->xfn )        ? ' rel="'    . esc_attr( $item->xfn        ) .'"' : '';
    $attributes .= ! empty( $item->url )        ? ' href="'   . esc_attr( $item->url        ) .'"' : '';


    $item_output = $args->before;
    $item_output .= '<a'. $attributes . $class_names .'>';
    $item_output .= $args->link_before .apply_filters( 'the_title', $item->title, $item->ID );
    $item_output .= '</a>';
    $item_output .= $args->after;

    $output .= apply_filters( 'walker_nav_menu_start_el', $item_output, $item, $depth, $args );
    }
}

Then in your template header.php

<?php 

    $defaults = array(
      'theme_location'  => 'main-menu',
      'menu'            => '',
      'container'       => '',
      'container_class' => '',
      'container_id'    => '',
      'menu_class'      => 'button-group',
      'menu_id'         => '',
      'echo'            => true,
      'fallback_cb'     => 'wp_nav_menu',
      'before'          => '',
      'after'           => '',
      'link_before'     => '',
      'link_after'      => '',
      'items_wrap'      => '<ul class="%2$s" role="navigation">%3$s</ul>',
      'depth'           => 0,
      'walker'          => new p2p_foundation_walker()
    );

    wp_nav_menu( $defaults );

      ?>

Should work perfect when you setup your custom menu.

Jeremy Englert over 5 years ago

Andrew, I was able to get the Foundation top-bar and off-canvas to play nicely with WordPress. In fact, the code posted above by Garet is very similar to what I used.

Feel free to download the files and take a peak at/steal the code. You will find them in the Library > Joints.php file (which is basically a custom functions.php file).

I didn't remove the WP classes though, as many of those can come in handy during development.

www.jointswp.com

Andrea Sciamanna over 5 years ago

None of the walkers solution worked for me.
Jeremy's solution did it instead.

Thanks Jeremy!

Rui Alexandre over 5 years ago

Garet - you walker doesn't allow dropdown menus, right?

Courtney - I tried yours, but the dropdown was also flawed; the submenus were visible, for example.

...or was I doing something wrong?

Andrew Munroe over 5 years ago

Hi Rui, if you inspect your menu, are the submenu items wrapped in <ul class="dropdown"></ul>?

Rui Alexandre over 5 years ago

Hello, Andrew.

Nope, they have the "menu" and "sub-menu" classes.

I wonder if I'm only getting the fallback version of the menu :X

https://www.dropbox.com/s/s6zvpujln79lbse/Screenshot%202014-01-02%2019.16.56.png

Rui Alexandre over 5 years ago

A friend of mine helped me with this problem... for those on a beginner level like me, it has to be said that the code to place on your header.php should be something like this:

<?php wp_nav_menu( array( 'theme_location' => 'main-menu', 'walker' => new Top_Bar_Walker(), 'menu_class' => 'right' ) ); ?>

...with a special focus on the " 'walker' => new Top_Bar_Walker()" part.

Hope this helps someone in the future - hell, even the future version of me.

Andrew Munroe over 5 years ago

Glad it was resolved. And as a handy tip for future reference, rather than attaching screenshots of code and sending the dropbox link, try using websites like http://jsfiddle.net or http://codepen.io - it's much easier for people to work with your code and help you out if they can edit it directly.

Jeff Kinley over 5 years ago

Jeremy,

From your post above:

Andrew, I was able to get the Foundation top-bar and off-canvas to play nicely with WordPress. In fact, the code posted above by Garet is very similar to what I used.

Feel free to download the files and take a peak at/steal the code. You will find them in the Library > Joints.php file (which is basically a custom functions.php file).

I have looked at the joints.php file and I don't see any code that looks anything like the walker that Garet posted. Am I missing something?

Thanks,

Jeff

Jeff Kinley over 5 years ago

Andrea,

Can you tell me how you were able to make Jeremy's solution work? I looked in the joints.php file, but I can't find a custom walker.

Thanks,

Jeff

Chris Promotional over 5 years ago

I found this when working with Bootstrap 4 and it seems to also work with Bootstrap 5.

https://gist.github.com/awshout/3943026

I didn't try the other stuff listed in this thread, but have had success with this (example: http://eventshuttleservice.com)

I'm currently working on a new site that uses B5, so I'll let you know if I run into any issues.

Joseph Bramall over 4 years ago

Hi guys, i've got the menu walkers working ok, i'm currently using Courtneys. However i'm having problems with the drop downs not working.

I went through my plugins and deactivated them all and found out that ACF was conflicting with the menu. When Advanced Custom Fields are turned off the drop downs work fine.

When you click the main link that has a drop down then then it appears but takes you to a page. The drop downs should just appear on hover.

I've spoken to someone at ACF and they said to make sure that jQuery has been deregistered and in no conflict, and it has, so i'm not sure what's going on.

Has anyone else encountered this?

Jethin almost 4 years ago

Hi. I’ve created a WordPress plugin that allows theme developers to easily output a menu as a Foundation top bar. It’s aptly titled “Foundation Top Bar Navigation Menu” and is available for download at:

https://wordpress.org/plugins/foundation-top-bar-navigation-menu/

Thanks.