3

I'm attempting to add my logo to the middle of my navbar, and while looking at the nav walker class I couldn't figure what the best way to do this would be.

So my question is essentially how do I do that. the Walker_Nav_Menu() method start_el() seems to build only one li so where is it iterating over all of them and writing them to file.

2
  • what do you mean by middle of my navbar and what is the criteria for the particular <li>?
    – David Lee
    Commented Feb 17, 2017 at 19:13
  • middle as in <ul><li></li>"this is the middle"<li></li></ul>. I need to make it easy to change the logo as well. Commented Feb 17, 2017 at 21:32

3 Answers 3

1

You need to make your own walker menu (i am guessing you already know that), and the best way i think is overriding the function that ends each menu item which is end_el :

class logo_in_middle_Menu_Walker extends Walker_Nav_Menu {

    public $menu_location = 'primary';

    function __construct($menu_location_var) {
        // parent class doesnt have a constructor so no parent::__construct();
        $this->menu_location = $menu_location_var;
    }

    public function end_el(&$output, $item, $depth = 0, $args = array()) {
        $locations = get_nav_menu_locations(); //get all menu locations
        $menu = wp_get_nav_menu_object($locations[$this->menu_location]); //one menu for one location so lets get the menu of this location
        $menu_items = wp_get_nav_menu_items($menu->term_id);

        $top_lvl_menu_items_count = 0; //we need this to work with a menu with children too so we dont use simply $menu->count here
        foreach ($menu_items as $menu_item) {
            if ($menu_item->menu_item_parent == "0") {
                $top_lvl_menu_items_count++;
            }
        }

        $total_menu_items = $top_lvl_menu_items_count;

        $item_position = $item->menu_order;

        $position_to_have_the_logo = ceil($total_menu_items / 2);

        if ($item_position == $position_to_have_the_logo && $item->menu_item_parent == "0") { //make sure we output for top level only
            $output .= "</li>\n<img src='PATH_TO_YOUR_LOGO' alt='' />"; //here we add the logo
        } else {
            $output .= "</li>\n";
        }
    }
}

i am assuming that if its a menu with an uneven number of item say 5 the logo will be after the third element, also that this is only for top elements only.

you have to use it like this in the menu location:

<?php
    wp_nav_menu(array(
            'theme_location' => 'footer',
            "walker" => new logo_in_middle_Menu_Walker('footer'),
    ));
?>

you have to supply the name of the theme location.

Here with 4 items:

enter image description here

Here with 5:

enter image description here

0
1

Modified David Lees nav walker class as for some reason it wouldn't quite work for me with submenu links. Unverified, but believe this was due to the menu items not having tidy/sequential menu_order values.

<?php 

class logo_in_middle_Menu_Walker extends Walker_Nav_Menu {

    public $menu_location = 'primary';

    function __construct($menu_location_var) {
        $this->menu_location = $menu_location_var;
    }

    public function end_el(&$output, $item, $depth = 0, $args = array()) 
    {
        $locations = get_nav_menu_locations();
        $menu = wp_get_nav_menu_object($locations[$this->menu_location]);
        $menu_items = wp_get_nav_menu_items($menu->term_id);

        $top_level_items = [];
        foreach ( $menu_items as $menu_item ) {
            if ( $menu_item->menu_item_parent == 0 ) {
                $top_level_items[] = $menu_item;
            }
        }

        $logo_position = ceil(count($top_level_items) / 2);

        if ( $item->menu_item_parent == 0 ) {
            $current_position = 0;
            foreach ( $top_level_items as $index => $top_level_item ) {
                if ( $top_level_item->ID == $item->ID ) {
                    $current_position = $index + 1;
                }
            }
    
            if ( $current_position == $logo_position ) {
                $output .= '</li>' . "\n";
                $output .= '<li class="logo">' . "\n";
                    $output .= '<img src="PATH_TO_YOUR_LOGO" alt="LOGO ALT" />' . "\n";
            }
        }
        
        $output .= "</li>\n";
    }
}
0

The best way to achieve the desired functionality, is to add a new menu item for the logo, by going to the Appearance > Menus, and set the class of the menu item to logo.

To enable custom CSS class in the menu, click the Screen Options then check the CSS Classes checkbox.

Let's assume you have a predetermined number of li items of 5.

<ul>
  <li class="logo">LOGO</li>
  <li>Item 1</li>
  <li>Item 2</li>
  <li>Item 4</li>
  <li>Item 5</li>
</ul>

Then set the main ul element css display attribute to flex:

ul {
  display: flex
}

And the li order number as follows:

ul li { order: 4; } 
ul li:nth-of-type(2) { order: 1; } /* For Item 1 */
ul li:nth-of-type(3) { order: 2; } /* For Item 2 */

Then for the logo class:

ul li.logo {
  order: 3;
}

You can learn for about the order property of the Flexible Box Layout

1
  • 1
    this can work as well for some people but you don't need to use the flex part of the answer because because wp allows you to order your menu items within the appearence > menu settings. Commented Feb 22, 2017 at 18:30

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.