WordPress Drop-down Menus with a Custom Walker

One feature of WordPress that I’ve never quite been happy with is the wp_nav_menu function. It has a lot of customizable options but one thing I think could be improved is its support for multiple levels (drop-downs.)

While working on a website for a client, we needed to add an arrow next to top-level nav that had children. We needed to:

  1. add a “dropdown” class to the top-level nav, and
  2. add <b class=”caret”></b> inside the link (yes, that’s bootstrap-inspired)

wp_nav_menu doesn’t support either. After some brainstorming, I had three possible ideas:

  1. Buffer the wp_nav_menu output (aka set the “echo” flag to false) and use regex to parse the HTML and add what we need
  2. Make use of a PHP class like DOMDocument to traverse the HTML and add what we need
  3. Write a custom walker and add what we need before we ever call wp_nav_menu

I’ve been looking for an excuse to get into further WordPress development so I decided to use a custom walker.

Modifying the Walker

I couldn’t find muchuseful information pertaining to my need so I dug into the WordPress core and found two files in /wp-includes, class-wp-walker.php and nav-menu-template.php.

Through some trial and error I found that the display_element function in class-wp-walker.php would allow me to append the class I wanted. Here’s what that code looked like (placed in my theme’s functions.php):

That solved the first part of my problem, but the HTML modification issue had yet to be tackled. While experimenting, I came across the start_el function that looked like I could append some HTML. I copied the entire start_el function to functions.php and added the following just before the closing </a> tag:

It’s possible to search for the “dropdown” class because display_element is called before start_el.

Anyway, this worked like a charm but was uber bulky – I love simplicity. I finally had my “D’OH” moment when I realized that it’s possible to append my HTML directly in the display_element function. I was looking at start_el and noticed it calling $item->title. $item is the same as $element in display_functions, so I appended

to my custom display_element function and BINGO!

Final Code

Here’s the final code (placed in the theme’s functions.php file):

One response to “WordPress Drop-down Menus with a Custom Walker”

  1. […] a bit of searching and thanks to Benjamin Uzelac and the ever trusty WordPress Codex, I found this solution to add to the function.php […]

Leave a Reply

Your email address will not be published. Required fields are marked *