{"id":11187,"date":"2012-08-10T17:23:36","date_gmt":"2012-08-10T15:23:36","guid":{"rendered":"https:\/\/www.saasweb.agency\/blog\/wordpress-creating-truly-custom-navigation-with-the-walker_nav_menu-class\/"},"modified":"2026-10-27T08:15:51","modified_gmt":"2026-10-27T07:15:51","slug":"wordpress-creating-truly-custom-navigation-with-the-walker_nav_menu-class","status":"publish","type":"post","link":"https:\/\/www.saasweb.agency\/en\/blog\/wordpress-creating-truly-custom-navigation-with-the-walker_nav_menu-class\/","title":{"rendered":"WordPress: Creating Truly Custom Navigation with the Walker_Nav_Menu Class"},"content":{"rendered":"<p><img decoding=\"async\" src=\"https:\/\/www.saasweb.agency\/wp-content\/uploads\/2011\/11\/wordpress-logo.png\" alt=\"\" title=\"WordPress Logo\" width=\"150\" height=\"150\" class=\"alignleft size-full wp-image-549\" srcset=\"https:\/\/www.saasweb.agency\/wp-content\/uploads\/2011\/11\/wordpress-logo.png 150w, https:\/\/www.saasweb.agency\/wp-content\/uploads\/2011\/11\/wordpress-logo-50x50.png 50w, https:\/\/www.saasweb.agency\/wp-content\/uploads\/2011\/11\/wordpress-logo-100x100.png 100w, https:\/\/www.saasweb.agency\/wp-content\/uploads\/2011\/11\/wordpress-logo-140x140.png 140w\" sizes=\"(max-width: 150px) 100vw, 150px\" \/>It often happens that a website navigation should display more than just the page name, including related information such as the description, the featured image, or anything else&#8230; To gain control over this, you need the Walker_Nav_Menu class. <\/p>\n<p><u>Procedure<\/u><br \/>\nEnter the following code into your functions.php; it corresponds to WordPress&#8217;s own code. This is where the desired changes will then be implemented. <\/p>\n<pre class=\"wp-block-code\"><code>class Custom_Walker extends Walker_Nav_Menu{\n\n  function start_el(&$output, $item, $depth, $args){\n    \n    $classes = empty ( $item->classes ) ? array () : (array) $item->classes;\n    $class_names = join(\" \", apply_filters(\"nav_menu_css_class\", array_filter($classes), $item));\n\n    ! empty ($class_names) and $class_names = \" class='\" . esc_attr($class_names) . \"'\";\n\n    $output .= $indent . \"<li id=\"menu-item-&quot; . $item-&gt;ID . &quot;\" .=\"\">\";\n\n    $attributes = \"\";\n\n    ! empty($item->attr_title) and $attributes .= \" title='\" . esc_attr($item->attr_title) . \"'\";\n    ! empty($item->target) and $attributes .= \" target='\" . esc_attr($item->target) . \"'\";\n    ! empty($item->xfn) and $attributes .= \" rel='\" . esc_attr($item->xfn) . \"'\";\n    ! empty($item->url) and $attributes .= \" href='\" . esc_attr($item->url) . \"'\";\n\n    $title = apply_filters(\"the_title\", $item->title, $item->ID);\n\n    $item_output = $args->before . \"<a>\" . $args->link_before . $title . \"<\/a> \" . $args->link_after. $args->after;\n\n    \/\/ Since $output is called by reference we don't need to return anything.\n    $output .= apply_filters(\"walker_nav_menu_start_el\", $item_output, $item, $depth, $args);\n  }\n}<\/li><\/code><\/pre>\n<p>What do we want to change now? For example, instead of a &lt;ul>&lt;li> navigation, we want simple &lt;div> elements for the individual navigation items. Additionally, we want the featured image below it and the description (from the menu). It would look like this, for example:   <\/p>\n<pre class=\"wp-block-code\"><code>\/\/ Add these lines in order to fetch the additional information you wish to display\n\n\/\/ We need the target page id in order to fetch the page image\n$page = get_page_by_path(basename($item->url));\n$page_id = $page->ID;\n\/\/ We should check if there is an image set or not, but we are lazy for this example\n$image_url = get_the_post_thumbnail( $page_id, 'custom-image-preview' );\n\/\/ Same thing for the description\n$description = esc_attr( $item->description );\n\n\/\/ Remove the li\n\/\/ Instead of $item_output = $args->before . \"<a>\" . $args->link_before . $title . \"<\/a> \" . $args->link_after. $args->after;\n$output .= \"\";\n\n\/\/ Change the output like you need it\n$item_output = $args->before . \"<div class=\"container-main\"><a>\" . $args->link_before . $title . \"<\/a><div class=\"page-image\">\" . $image_url . \"<\/div><div class=\"menu-page-description\">\" . $description . \"<\/div><\/div> \" . $args->link_after. $args->after;<\/code><\/pre>\n<p>To ensure it is actually displayed, the wp_nav_menu call must be modified. For example, like this: <\/p>\n<pre class=\"wp-block-code\"><code>wp_nav_menu( array( 'theme_location' => 'my-custom-navigation', \n    'menu' => '', \n    'container' => 'nav', \/\/ Auto wrap navigation in &lt;nav> area\n    'container_class' => FALSE, \n    'container_id' => FALSE, \n    'menu_class' => FALSE, \n    'menu_id' => FALSE, \n    'echo' => true, \n    'fallback_cb' => 'wp_page_menu', \n    'before' => '', \n    'after' => '', \n    'link_before' => '', \n    'link_after' => '', \n    'items_wrap' => '%3$s', \/\/ Remove the ul container\n    'depth' => 0, \n    'walker' => new Custom_Walker ) );<\/code><\/pre>\n","protected":false},"excerpt":{"rendered":"<p>It often happens that a website navigation should display more than just the page name, including related information such as the description, the featured image, or anything else&#8230; To gain control over this, you need the Walker_Nav_Menu class. Procedure Enter the following code into your functions.php; it corresponds to WordPress&#8217;s own code. This is where \u2026<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[981,877,983],"tags":[1206,819],"class_list":["post-11187","post","type-post","status-publish","format-standard","hentry","category-programming","category-saas-web-info","category-tutorial","tag-walker_nav_menu","tag-wordpress"],"acf":[],"_links":{"self":[{"href":"https:\/\/www.saasweb.agency\/en\/wp-json\/wp\/v2\/posts\/11187","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.saasweb.agency\/en\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.saasweb.agency\/en\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.saasweb.agency\/en\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.saasweb.agency\/en\/wp-json\/wp\/v2\/comments?post=11187"}],"version-history":[{"count":0,"href":"https:\/\/www.saasweb.agency\/en\/wp-json\/wp\/v2\/posts\/11187\/revisions"}],"wp:attachment":[{"href":"https:\/\/www.saasweb.agency\/en\/wp-json\/wp\/v2\/media?parent=11187"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.saasweb.agency\/en\/wp-json\/wp\/v2\/categories?post=11187"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.saasweb.agency\/en\/wp-json\/wp\/v2\/tags?post=11187"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}