Ask your WordPress questions! Pay money and get answers fast! Comodo Trusted Site Seal
Official PayPal Seal

walker class for custom menu mark-up WordPress


Hi Guys, newbie here from South Africa. Just stumbled upon this awesome site and hope you can help me as I'm at my wits end, I'm not a php dev and have given up on this quest.

I need custom markup for my wordpress menu. I'm already using a custom walker class and it's working to a certain extend, but not quite as required.

Here is the markup I require wordpress to output for my menu. This is a three-level deep menu with custom classes and some IE conditional tags. Menu is a horizontal drop-down menu.

<div id="menuWrap">
<ul id="menu-mainnav">
<li class="li-top"><a class="top" href="/">Home</a></li>
<li class="li-top"><a class="top sub" href="#">About<!--[if gte IE 7]><!--></a><!--<![endif]-->
<!--[if lte IE 6]><table><tr><td><![endif]-->
<ul class="sub-menu">
<li><a href="/about/introduction">Introduction</a></li>
<li><a href="/about/history-of-school">History</a></li>
<!--[if lte IE 6]></td></tr></table></a><![endif]-->
<li class="li-top"><a class="top sub" href="#">Academics<!--[if gte IE 7]><!--></a><!--<![endif]-->
<!--[if lte IE 6]><table><tr><td><![endif]-->
<ul class="sub-menu">
<li><a href="/academics/overview">Overview</a></li>
<li><a class="subSub" href="#">Senior Primary<!--[if gte IE 7]><!--></a><!--<![endif]-->
<!--[if lte IE 6]><table><tr><td><![endif]-->
<ul class="ul-two">
<li><a href="/academics/senior-primary/afrikaans">Afrikaans</a></li>
<li><a href="/academics/senior-primary/art">Art</a></li>
<!--[if lte IE 6]></td></tr></table></a><![endif]-->
<!--[if lte IE 6]></td></tr></table></a><![endif]-->

Here is my current mark-up

- I'm missing the IE conditional statements.
- When the first ul is nested inside a li, the <a> tag inside the li should have a class "sub".
- When the second ul is nested inside a li, the <a> tag inside the li should have a class "subSub"
- Only the parent li's should have class 'li-top', all other li's should have no classes.
- The second nested ul should have class 'ul-two'

<div id="menuWrap" class="menu-mainnav-container">
<ul id="menu-mainnav" class="menu">
<li class="li-top"><a class="top" href="" class="active">Home</a></li>
<li class="li-top"><a class="top" href="">About</a>
<ul class='sub-menu'>
<li class="li-top"><a class="top" href="">Introduction</a></li>
<li class="li-top"><a class="top" href="">History</a></li>
<li class="li-top"><a class="top" href="">Academics</a>
<ul class='sub-menu'>
<li class="li-top"><a class="top" href="">Overview</a></li>
<li class="li-top"><a class="top" href="">Senior Primary</a>
<ul class='sub-menu'>
<li class="li-top"><a class="top" href="">Afrikaans</a></li>
<li class="li-top"><a class="top" href="">Art</a></li>

Here is my half working walker class.

class MFC_Walker_Nav_Menu extends Walker_Nav_Menu {
* @see Walker::start_el()
* @since 3.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 int $current_page Menu item ID.
* @param object $args
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;
$classes[] = 'sybaweb' . $item->ID;

$class_names = join( ' ', apply_filters( 'nav_menu_css_class', array_filter( $classes ), $item, $args ) );
$class_names = ' class="li-top"';

$class_link = ' class="top" ';

$id = apply_filters( 'nav_menu_item_id', 'menu-item-'. $item->ID, $item, $args );
$id = strlen( $id ) ? ' id=""' : '';

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

$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 ) .'"' : '';

// new addition for active class on the a tag
if(in_array('current-menu-item', $classes)) {
$attributes .= ' class="active"';

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

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

// edit nested ul
function start_lvl(&$output, $depth)
$indent = str_repeat("\t", $depth);
$output .= "\n$indent<ul class='sub-menu'>\n";


Answers (2)


Abdelhadi Touil answers:

I think tou can add manually links to your menu, it's easier than trying to make Wordpress outputs it. Sometimes I prefer build a manual menu in such case.
For adding classes to each menu item, Wordpress can do this, here is how:
[[LINK href=""]][[/LINK]]
Hope this helps you.
Good luck.

kingr comments:

I will give this a shot, but how will I go about the IE conditional statements that I need? These are critical.

I can't use jquery here, this menu needs to work in IE6 without query.

Abdelhadi Touil comments:

Do you use a menu you find on the net or you'v coded it? If it's a ready to use menu so please give us the link.
I think ie6 is dead :D

kingr comments:

The css of the menu is already coded. I have the css, not link to actual menu.

I just need the mark-up output to look as above. I know ie6 is dead, but this project unfortunatly requires ie6 compatibility.

I can easily refactor the menu mark-up with jquery to look like I want it to, but the jquery functions I use to do this does not work in ie6. So this is not a viable solution.

kingr comments:

This can be done with the walker class. I just don't have the ability to code the class myself, I'm a front-end dev, php very rusty.


Martin Pham answers:

please try this script, I have checked, it can work on IE6+
[[LINK href=""]][[/LINK]]

Using [[LINK href=""]]wp_nav_menu[[/LINK]] to do this.


if ( has_nav_menu( 'primary' ) ) {
$args = array(
'theme_location' => 'primary',
'container' => '',
'menu_class' => 'menu menu-primary superfish',
'echo' => 0,

$nav = wp_nav_menu( $args );
echo '<div id="nav-menu">'.$nav.'</div>';

kingr comments:

Not really what I'm after. I need the menu mark-up to be as above, the css for the menu is already working. I'm not keen on reinventing the wheel with the menu.

Initially the menu was hard coded in the wp and it's mark-up is as above. Now the menu gets generated dynamically with wp and I want the output to be as the previous static defined mark-up. This way I don't even need to touch the css as it worked when it was statically defined. I'm fixing this menu for a client, I did not define the initial static menu (who on earth does this!)

kingr comments:

hang on, giving this another look and will try to implement.

kingr comments:

I need descriptive (spoon feeding) help, tried your example code snippet with no show of the menu. I think my menu does not have an assigned theme location. This is a custom theme that was written by someone else.