Hay & Kilner Website Refresh
Hay & Kilner, a Facelift to an Existing CMS Driven Website
2 Comments
Walk To The World Cup - Campaign for Be Air Aware
Walk to the World Cup, a bespoke WordPress plugin
0 Comments
Service Network
Service Network, CMS based events driven website
0 Comments
Numark Pharmacists
Numark Pharmacists, CMS based website and membership based extranet
0 Comments

Adding a CSS Class to the the Last LI Generated by wp_nav_menu()

One of the great new features introduced in the latest WordPress (3.0) update is the menu feature. Now I’m not going to go an about how great all of this is and how life will never be the same because that’s getting a little tired now, but I did find myself needing to style the last items in both menu’s I was using to remove a pipe character from the footer menu and a background image from the main Nav. So for anyone interested heres how to add a class name to the the last LI in an UL generated by wp_nav_menu().

/* Add last_item class to last li in wp_nav_menu lists*/
function add_last_item_class($strHTML) {
	$intPos = strripos($strHTML,'menu-item');
	printf("%s last_item %s",
		substr($strHTML,0,$intPos),
		substr($strHTML,$intPos,strlen($strHTML))
	);
}
add_filter('wp_nav_menu','add_last_item_class');

You can add this example anywhere in your functions.php file. It’s worth mentioning that this example relies on you using the default list item classes provided by wp_nav_menu, but you can easily update this by adding the li class you are using:

$intPos = strripos($strHTML,'my-li-class-name');

There are tonnes of ways to do this but this is clean and simple string manipulation, so the overheads are quite low compared with the PREG/EREG approach.

16 Comments

  1. steve coy
    Posted September 12, 2010 at 10:06 am

    This is great! How can you get it to apply to nested lists (2-3 levels deep)? I would like to use this to effectively replace the :last-child pseudo-class. Currently it only works on the VERY last in wp_nav_menu, not the last within each .

  2. Posted September 12, 2010 at 9:20 pm

    Hi Steve, thanks. You might be better off trying to use preg_match if you want to add a class recursively, the strpos approach is simpler but not as flexible. Alternatively you could use jQuery’s pseudo-class selector along side your CSS pseudo which should make IE6 play nicely :), something along the lines of:

    $(‘ul li:last-child’).addClass(‘last’);

  3. Posted September 15, 2010 at 10:31 am

    Steve, few days ago I was dealing with the same problem and have quickly solved that with this code http://www.bouk.info/wordpress/wpnavmenu-adding-class-to-the-all-last-items/

    Hope it helps.

  4. Posted September 17, 2010 at 5:01 pm

    I am unfamiliar enough(without being unlazy and researching) with the functions above to figure out how to apply a class to the first child as well. I am working on a menu with end caps that are different from the middle list items.

    Right now I’m using the available add custom classes option in the Menu setup, but fear someone breaking the menu due to not knowing what to do.

    Any help appreciated :)

  5. Posted September 17, 2010 at 8:23 pm

    Hi Michael, strripos finds the last occurrence of the target string so if you replace it with stripos, you should be laughing. Something like:

    function add_first_item_class($strHTML) {
      $intPos = stripos($strHTML,'menu-item');
      printf("%s first_item %s",
        substr($strHTML,0,$intPos),
        substr($strHTML,$intPos,strlen($strHTML))
      );
    }

    Hope that helps…

  6. Posted September 24, 2010 at 9:33 am

    I needed something like this, only then a first and last item for each sub-menu, for making it easier to add rounded corners in css. So made a custom version of this:

    /* Add a first and last list item */
    function add_last_item_class($strHTML) {
      if (preg_match_all('/(.*)/Uis', $strHTML, $return)) {
        for($i=0; isset($return[1][$i]); $i++) {
          $submenu = "\n\t" . $return[1][$i] . "\t\n";
          $strHTML = str_replace($return[0][$i], $submenu, $strHTML);
        }
      }
      echo $strHTML;
    }
    add_filter('wp_nav_menu','add_last_item_class');

  7. Posted September 29, 2010 at 3:59 pm

    Hi, really useful script, however I’m now needing it to apply an inline style to the class=” and not to the id att which your script seems to do.. any ideas? thanks.

  8. Posted September 29, 2010 at 4:28 pm

    Hi just to say I sorted my problem.. I didn’t realise in WP 3 you can assign your own class to any menu item form the ‘screen options’ when in the menu page in the backend. (sweet!)

  9. DaChin
    Posted September 30, 2010 at 6:29 am

    I’m not using English as my major language, but all I can say is “Great Post” !!!

  10. Posted March 16, 2011 at 9:01 pm

    Great work:)

    I’m using CSS to do that trick.

    .menu li:first-child{

    }
    .menu li:last-child{

    }

    best regards

  11. Posted April 13, 2011 at 5:40 pm

    @Pawiksd
    Not all versions of Internet explorer support child selectors.

  12. Posted April 21, 2011 at 9:31 am

    Great post but i use the solution of @Pawiksd and, for me, is faster and easier.

    Anyway, good tips.

  13. Posted May 26, 2011 at 7:49 am

    I am always searching online for articles that can help me educate myself. Looking forward to another great post. Thanks

  14. Posted June 7, 2011 at 8:17 am

    Wouldn’t you agree, that this is much cleaner:

    function add_last_item_class( $items ) {
    $items[count($items)]->classes[] = 'last';
    return $items;
    }
    add_filter( 'wp_nav_menu_objects', 'add_last_item_class' );

  15. Posted June 7, 2011 at 9:25 am

    Hi Konstantin, Yes it is clean code, nice work.

    Although it could get called quite a few times in an execution, not that this would be an issue with most WP builds.

  16. Posted August 24, 2011 at 3:21 am

    Thanks John, worked great, much more reliable than using :last-child pseudo class.

Post a Comment

Your email is never shared. Required fields are marked *