Easily modifying your navigation in WordPress usually requires diving into your theme’s code a bit. For novice users, this can be pretty tough. What if I told you that you could that you could set it and forget it even if you want to make changes later?
That’d be a pretty cool, right?
I’m going to give you a few lines of code that’ll make your life immensely easier in the future and allow you to change your navigation whenever you want from the WordPress backend.
Using bookmarks for your navigation
I put out a call for people to start thinking about using bookmarks more effectively a few weeks back, but no one really answered. I suppose I’ll have to step up and show you a cool way to use them myself.
Bookmarks are those things called Links in your WordPress dashboard. We’re going to use them to create our navigation menu. Go to Link Categories. From there, create a new category. I’m naming my category Navigation.

Once you’ve created your category, you need to create your links. Go to Add New under the Links menu in your WordPress dashboard. Type a name for the link and a URL. The most important step here is to select the category that you created in the previous step. There are other things you can enter as well but aren’t necessary.
Create as many links as you like. You can change them, update them, or add new ones later.

Creating your custom menu
If you’re using one of my themes, just go to my support forums, and I’ll show you how to implement this into your theme.
Now, what we’re going to do is add a new function to our theme’s functions.php file. Skip to the next section of this tutorial if your theme uses the wp_page_menu() function to create its menu.
<?php
function custom_bookmark_menu($cat_id = false) {
$page_uri = str_replace("/", "", $_SERVER['REQUEST_URI']);
$class = "page_item";
$bookmarks = get_bookmarks(array('category' => $cat_id));
$menu = '<div id="page-nav"><ul class="bookmarks xoxo">';
foreach($bookmarks as $bookmark) :
if(!$page_uri && (get_bloginfo('url') == $bookmark->link_url))
$class .= " current_page_item";
elseif($page_uri && strchr($bookmark->link_url, $page_uri))
$class .= " current_page_item";
$menu .= '<li class="' . $class . '"><a href="' . $bookmark->link_url . '" title="' . $bookmark->link_name . '" rel="' . $bookmark->link_rel . '">' . $bookmark->link_name . '</a></li>';
endforeach;
$menu .= '</ul></div>';
echo $menu;
}
?>
Find your theme’s navigation menu and change it to something like this. Add any classes and/or IDs that your theme’s menu would have. Also change the 3 to the ID of the link category you chose in the first step.
<div id="page-nav">
<ul>
<?php custom_bookmark_menu(3); ?>
</ul>
</div>
Just save your files and check out your new menu with your custom links.
Filtering wp_page_menu
If your theme uses the new wp_page_menu() function introduced in WordPress 2.7, you can use this function and not have to edit your template files. This is the method you would use with my Hybrid theme.
Open your theme’s functions.php file and paste this code in (change the 3 to the ID of your link category:
<?php
add_filter('wp_page_menu', 'custom_bookmark_menu');
function custom_bookmark_menu($menu) {
$menu = false;
$page_uri = str_replace("/", "", $_SERVER['REQUEST_URI']);
$class = "page_item";
$bookmarks = get_bookmarks(array('category' => 3));
$menu = '<div id="page-nav"><ul class="bookmarks xoxo">';
foreach($bookmarks as $bookmark) :
if(!$page_uri && (get_bloginfo('url') == $bookmark->link_url))
$class .= " current_page_item";
elseif($page_uri && strchr($bookmark->link_url, $page_uri))
$class .= " current_page_item";
$menu .= '<li class="' . $class . '"><a href="' . $bookmark->link_url . '" title="' . $bookmark->link_name . '" rel="' . $bookmark->link_rel . '">' . $bookmark->link_name . '</a></li>';
endforeach;
$menu .= '</ul></div>';
return $menu;
}
?>
Just save the file and you’ll be finished. You didn’t have to edit a single template file in your theme.
Problems with using this method
While this will make updating your navigation menu much easier because it’s all done from your WordPress dashboard, there are still some issues.
- Dynamic menu highlighting
I don’t know of any way that you could dynamically highlight the link to the page the visitor is on. If anyone knows how this can be accomplished, I’ll be happy to update the post with the information.Code has been updated to account for dynamic menu highlighting. - Drop-down lists
While it’s not impossible to add a drop-down menu, it’s much more complicated using this method.
Enjoy your new navigation menu
After the initial setup of your menu, you don’t have to edit the code whenever you want to change links. Just create, update, and/or delete links as you see fit from your WordPress dashboard. Of course, you might have to style it if you’re creating your own theme.
I encourage you all to help me think of more creative ways to use our WordPress bookmarks. Since the Era of the Blogroll is now dead, we may as well do something useful with them. Another thing I could do is just package this thing up as a plugin whenever I’m feeling a little less lazy.
Some of you theme developers may wonder why I didn’t filter wp_list_pages() in the first method, but there’s a good reason for this. Users may want to have an actual page menu in their sidebar and use a widget to do so. Using a filter for this would filter all page lists. It is unlikely that wp_page_menu() will be used more than once on a page, which is why I used a filter in the second method.
Good tip – I’ve been using this for quite a while – creating sub navigation on more complex sites – example :category: subnav1, subnav2 etc – There’s a plugin that allows you to choose pages for linking, however this doesnt work in the bookmarks section – only posts and pages.
I used a similar system on this site:
http://www.barnsleyhospital.nhs.uk/a-to-z
The ‘A to Z’ needed to be separate from the main content structure because certain medical terms such as “Paediatrics” are often overlooked by users simply looking for terms such as “Children” or “Baby”.
All I had to do was to create a sub-category for each letter of the alphabet and then ask users to cross link their pages. It worked pretty well.
What a great idea. Allows one to maintain those menus right there in the WP back-end. Thanks for this.
Justin,
I found this plugin. Give it a try
Menu Creator WP Plugin
This brings up an idea I’ve been contemplating for my new site design. While not utilizing links, I want to create two menus (though in theory, three or more would be just as easy once implemented). I would probably use a filter on the wp_page_menu similar to the solution above based on tags. One menu would load all pages with the “menu1″ tag and the other for all the “menu2″ tags. Would this be the best way to tackle it?
kel — Cool. Link to a site to show it off if you want to.
mkjones — That’s an awesome example of how bookmarks can be used creatively.
Lyndi — Yeah, I would use it for my own site if I knew how to dynamically highlight the links with this method.
Agus MU — I deleted the link you posted because it only went to a zip file that had nothing in it.
Derek Perkins — You’ll just have to play around with different concepts and ideas. I only suggest this method if you don’t feel comfortable mucking around in the code every time you want to change a link.
Nice. I love when people give tangible code tutorials instead of just wrapping it up in a plugin.
I’ve had some success working around the highlighting issue with jQuery. Adding classes to the link via jQuery according to what the link contains.
kristarella — I prefer not to use plugins if it would be just as easy to code it myself. Many times, plugins will add extra database queries as well.
I didn’t even think about using jQuery to highlight the menu items. That’s a great idea. I wouldn’t recommend it unless already using jQuery for something else on the site though. It would be a bit much just for the highlighting.
It’d be great to add a sort here as well, this template tag accomplishes the same thing, but allows for a little more control:
<?php wp_list_bookmarks('categorize=0&title_li=&category=12&before=&after=&show_images=0&show_description=0&orderby=rating&category_before=&category_after='); ?>Great writeup though. I’m interested as well in dynamic menu highlighting – perhaps a start would be to add a counter that would add a ‘link1′ ‘link2′, etc to each link – that would at least get a class in there. Than, you could at least use the:
to add a body class on that page that than targets the ‘link1′ or ‘link2′ and changes it. Just a thought.
if ( strpos( $_SERVER[`REQUEST_URI'] , '/page-slug' ) === 0 )That was the 2nd example I was trying to show
kristarella – could you post your jquery idea here (or somewhere?)
Justin — I totally agree regarding plugins. I try to keep them to a minimum. They often add extraneous code and I hate being dependent on them if they stop being developed.
Yeah, jQuery might be a bit much just for the nav, but if it’s already loaded might as well!
Jeromy — the jQuery code for adding nav classes would be something like the following in the header area.
Any list item containing the word “About” would get a class of “about”. Then you would style accordingly. To get highlighting on the about page I would use specific CSS for that page by having page specific body classes. So, my CSS would be
div#page-nav li.about {background-color: #ffd;} /* usual color */body.about div#page-nav li.about (background-color: #ddf;} /*about page color */
Alternatively you could wrap your script in conditional tags to apply, for example, “current-page” classes to those items.
Jeromy — You can sort with
get_bookmarks(). I’ll look over your second example as well.great points guys – the one underlying problem is if I’m building sites for clients and they’re adding menu links like this, ad nauseum, I guess that’s where it has to be “really” dynamic. Guess we’ll all have to really think “outside” the box
– I normally just use wp_list_pages, but I have a client right now where that frankly just won’t work – so some pages will have an “on” state and others won’t. Don’t know if it’s a big deal to them, but I’d sure love to figure it out!
If it was for a client and you wanted to keep things dynamic, I might rip the code out of wp-includes/bookmark-template.php and add classes into the bookmark output.
I think I figured out the solution for adding dynamic highlighting.
First, we need to get the the page URL (replacing the slash to keep consistency with bookmarks):
Then, inside the
foreachloop, we’ll do a few conditional checks to get the class:All that would be left at this point is adding the
$classvariable as an XHTML class on the bookmarks.wow – impressive man! Let us know if/when you get it finalized – we should contribute this back to the whole community (would probably be better suited in functions.php no?)
Jeromy — I just updated the post with the new code and cleaned up everything else a bit as well.
This is the alternate way and look interesting.
For me it’s too complicated but I like the idea
Wow, you did it man! Looks great – ran into a weird occurrence though – check out this page:
http://www.lifewaytempsite.com.php5-4.websitetestlink.com/knowledge-base
Notice both the Browse and Search links on the left are “on” – even though the url matches only one of the links. Strange?? Also, wasn’t sure from your earlier answer, but where on this line would I add the ‘orderby’ attribute:
$bookmarks = get_bookmarks(array('category' => $cat_id));figured out the sorting, and it would seem that no matter how they’re sorted, the link below the “current” link is always given the “current_page_item” class as well.
Great tutorial.Thank you.
Here via Lyndi’s Nice2All site, great tip and I’ll give it a try.
Mik — It’s definitely worth trying out if you want easier maintenance of your navigation.
Trying on a copy of WordPress on my local machine, using hybrid with leviathan child theme. It is probably obvious, but how do I get the links in an order I like, I currently have the about page listed first then home, how do I get home to always be the first listed?
Great tutorial and innovative idea. I will surely put this to use on some of my client’s websites.
-
Thanks
TJ
Is it possible to do this if you are running your blog on wordpress.com or do you need to have to host wordpress yourself?
TJ — No problem. This would be an ideal solution for clients, especially those that don’t know anything about code.
Eskil — You’ll need to ask that over at the WordPress.com support forums. I only deal with self-hosted WordPress installs.
Just spotted this post. A couple of weeks ago I released a very simple plugin that allows to manage your navigation in a very easy way without any custom PHP coding. I think it’s very relevant to your post and would be useful for WP newbies as well as savvy users. The plugin also has settings for conditional navigation appearance – it allows custom navigation widgets to appear on specific pages or sections of your WP blog/site.
Here is a link to the plugin if you would to take a look http://wordpress.org/extend/plugins/simple-sidebar-navigation
Max — It certainly looks like it would be a cool plugin. The only problem I see is there are no instructions for how to use it without touching theme template files.
I’d rather see a solution that filters the
wp_page_menu()function for the top navigation, which I think you should be able to do with your plugin. We should try our best to keep users out of the templates.Justin, the only time when you’d need to touch the theme template file is when you need top/horizontal navigation (which is optional and doesn’t even exist in some themes at all). Otherwise, if you have already defined sidebars by your theme – all you need to do is to add navigation widgets to them via Widgets dashboard.
Max — Yes, that’s exactly my point. The only part of your plugin that’s relevant to this post is when using top navigation. Therefore, it is not “optional” in this context. Adding things anywhere else is outside the scope of this post.
You can probably show users how to filter
wp_page_menu()from their theme’sfunctions.phpand keep them out of the normal templates.What I’m doing is using the wp_list_pages function. It lets you filter pages out by meta data, so I just add a custom field called “navmenu” to each page I want listed, with a value of “topmenu”. Doing it this way, I have my top navigation filled with those pages, plus my footer menu showing all the pages with the “bottommenu” value. It isn’t a plug and play solution for the average user, but if it were embedded in themes, it would make menu creation and maintenance by users incredibly simple.
I see your point now, Justin. I’ll see if I can implement your suggestion about the wp_page_menu() filtering.
Fantastic, Justin!
I’m following up Mik’s last post though — what’s the best way to custom order/filter the nav instead of the default alpha-order?
Justin,
as usual great tutorial and great follow-up and comments!
Some ideas:
- why not using the “category_name” instead of “category_id”? cat names are more persistant and doesnìt changes between various installation etc. get_bookmarks() support category_name as well. You could then hardcode the function in your themes and just instruct the user to create the appropriate links category and fill it…
- For the ordering issue: I normally use the field “notes” filled with numbers: 0, 1, 2, and set get_bookmarks() with ‘order_by’ to ‘notes’
What do you think about it?
Stefano
Thanks for the tip, Stefano — I ended up using modified code from Jeromy’s post above and custom ordering is working great. I had to modify bookmark-template.php in order to stop if from adding additional code which was throwing off my css, but all works great.
To clarify from the last post– I ended up using wp_list_bookmarks function, which my theme had altered. Hence the modification to a file that doesn’t actually appear here.
Hi Justin Tadlock,
Nice Article. You have demonstrated nicely on how to create a menu bar using the links from a category. But i would like to know how to create menu bar using Link Categories? Do you u have any idea on it?
That almost give’s me what I need, quite a cool little code. Just really need to have the ability to at a drop down menu, then be able to add jQuery into it.
Justin – on your original code sample, once one of the if conditionals are met, then $class will always contain the appended current_page_item class for the items following it in the foreach loop. If you reset the $class variable inside the foreach loop, then everything will work out fine.
Very interesting article. I’ve started from your code to build a customizable menu for Thematic Framework for WordPress. It includes also drop-down subitems, using JS Superfish included with Thematic theme. I’ve added the ability to change item position on menu using the “rating” attribute of the link.
I’ve adapted your code for Thematic but I guess it can works with any theme just adding superfish js code to it.
The article is in italian but I tried to write a partial translation in english: http://www.matteostagi.it/a-customizable-menu-for-thematic-for-wordpress/
Brilliant solution. I have used bookmarks before as menu items, but was stuck with how to add the “current_page_item” class. This function works great.
One thing, I was having trouble with $class not clearing each time through the foreach. Moving the
$class = 'page_item';to just inside the foreach sorted that out.I also added the orderby=rating attribute when calling the bookmarks so as to give the end user an easy method of ordering their menu items. As main navigation is rarely more than 9 menu items, using the link’s rating (0-9) is an easy way to control what order the links are displayed in. To do so I simply changed:
– to –
And, one last change, as strchr() uses up more memory than strpos(), I changed:
– to –
Thanks again Justin!
Hi. I really appreciate this post. I added the following function to my functions.php file, so that I can use widget logic to display a link_category on any page and all of it’s sub-pages. I thought others might be interested in it too.
Here is an example of how to call it. Just place
is_page_or_subpage('technical-help')in your widget-logic box.I’d rather use the method above, but since I need drop down menus, I ended up using a neat little plugin to help accomplish essentially the same
http://txfx.net/code/wordpress/page-links-to/
@Eddie
Thanks for the tip on the “page-links-to” plugin. That is going to be really useful.
indeed, it is pretty flexible. the only menu call I need is wp_list_pages() and I can insert links to categories, external sites, or anything else as pages. one of the best aspects is the ease you now have to mix all those items while keeping full control over the order they are displayed. the only thing you cant do, but I would like to figure out a mod that allows it, is link to javascript or to # (click goes nowhere)
There still seems to be a problem with current_page_item classes in Hybrid. Adding Justin’s code gives me this:
Suggestions?
Try that again with the code:
How the hell do I add code into a comment?
Dave, you need to escape any HTML.
Thanks Kristarella, and sorry for spamming the comments Justin. OK, here’s my code (hopefully):
For anyone having trouble, make sure to make the changes recommended by Ryan in his comment from June 17 (http://justintadlock.com/archives/2009/01/06/easy-navigation-menus-in-wordpress#comment-133507)
Justin, it would be great if you would update the original posting with those changes.
I didn’t want to use the ratings to arrange sort my links, so I used the notes field instead, changing Ryan’s line
‘$bkmrkqry = ‘orderby=rating&category=’.$cat_id;’
with
$bkmrkqry = ‘orderby=notes&category=’.$cat_id;
Add a 0 in the Notes field of the link you want first, a 20 in the Notes for the link you want last, and some other number for each link in-between. Even though I only have ~9 links, I find it faster to re-arrange them this way, as you don’t have to shuffle them around.
Hi Justin,
Great info! Is there a way to add this to the existing page menu, so that the bookmarked links will be added to navigation, yet IN ADDITION to existing items? Right now, my existing pages are taken off the menu…
Thanks!
indeed, it is pretty flexible. the only menu call I need is wp_list_pages() and I can insert links to categories, external sites,
thank you for this tutorial and it is really useful to us in wordpress community.
thanks alot for this amazing tutorial, just what I was looking for
Regarding the current_page_item class issue not working for some people, I came up with a fairly rough way of handling it in jQuery:
Essentially what this is doing is getting the current URL and comparing the string to an unordered list of links, if the href matches it assigns the current_page_item to the parent
Obviously the script could be enhanced to handle slight differences in the URL, but it does work if they match exactly.