The Difficult Method (WordPress Codex Solution)

Please note that this solution is non productive whenever you want to have normal text as menu links. In case you want to have a navigation using images, this would be the solution for you. The main navigation from this website it is built using a background image and switch its position based on the ID of the menu item, with the help of CSS. This type of navigation can be done just using WordPress solution (next code), as we can’t assign ID’s dynamically, using WordPress Dynamic Menu Page Method, described later in tutorial.

<ul>
	<li class="current" id="home-item"> <a class="current" href="<?php bloginfo('url');?>"><span>Home</span></a></li>
	<li class="current"><a href="services"><span>Services</span></a>
<ul>
	<li><a href="services/subpage1">Subpage 1</a></li>
	<li><a href="services/subpage2">Subpage 2</a></li>
</ul>
</li>
	<li class="current" id="contact-item"> <a class="current" href="contact"><span>Contact</span></a></li>
</ul>

The first list item, Home, has a conditional to check if is home page it should set a class of “current” so you can display the current page in a different way, so the usability of the site will be increased.
The second list item has two sub pages, that using CSS, will show up as drop down. If the Services page will be active, WordPress will automatically assign a class of “current” to its list item.
In this method the “span” tag will help us to hide the text so we can view just the background image.
The example contains just 3 list items, but if we want to have more, it can can become very hard at some point, to maintain the menu. Plus, if you want to give your client the control over navigation this is not a viable solution.

WordPress Dynamic Menu Page Method

You can see a demo of this method, within a website I have developed. All of the menu there, is generated dynamically by the code described below.
You can see in that demo, that we can still assign background images and have in the same time real text. The text is wrapped with a “span tag” so we can use a CSS method called sliding doors to set images as background for this menu-items.

The dynamic solution would be:

<?php wp_list_pages('&title_li=&link_before="<span>"&link_after="</span>"&depth=2'); ?>

The Code Explained

This piece of code is a WordPress tag that calls the pages and set their titles a names. Also we want to display any sub page as a dropdown with the help of CSS so we specify a depth of 2.

	<?php wp_list_pages('&title_li=&depth=2'); ?>

If we want to display a higher number of sub pages, we just increase the number or remove “&depth=2” so it will display unlimited sub pages.
Because we want to set images as background for the menu items, we have to add a span tag:

<?php wp_list_pages('&title_li=&link_before="<span>"&link_after="</span>"&depth=2'); ?>

HTML Result:

Now we have a totally dynamic menu and submenu, that will display as HTML like so:

<ul>
    <li class="current"><a href="home"><span>Home</span></a></li>
    <li><a href="services"><span>Services</span></a>
        <ul>
	<li><a href="subpage-1">Subpage 1</a></li>
	<li><a href="subpage2">Subpage 2</a></li>
        </ul>
    </li>
</ul>

The CSS

Now we have the HTML dynamic generated, but we still need to customize it with CSS. We will do this in a separate lesson, where I will show you how to set up background images for menu items, as a Apple menu way.

WordPress Menu Page Highlighting With CSS

Now if you take a look the source code, you will see that WordPress outputs a “current_page_item” class to the corresponding li tag of the page where you are. Now is very easy, with the help of CSS, to display in bold, the current page link:

Highlight the parent page

li.current_page_item a {font-style:bold}

Highlight parent’s child page

What if you want to have the parent page bold, while you are on one if its subpage? WordPress comes in help again, outputting dynamically, a special class “current_page_ancestor”, so our code will look like that in this case:

li.current_page_ancestor a {font-style:bold}

That was it. I assumed in this article, that you already have basic CSS knowledge and you are aware of CSS specificity.

Some Helpful Plugins:

Page Exclusion

If you need to have some pages excluded from navigation you need the exclude pages plugin.

My Page Order

A really useful plugin is my page order plugin, which will allow you to order the pages in your menus.

Page Tree Overview

If it happens to work on a website with a lot of pages wordpress page tree will give you an overview of those and you can reach a specific page really quick in order to edit it.

Resources:

20 Responses

  1. I guess you are talking about sidebar navigation. If you go on WordPress.org forums, there are many topics regarding this. There is a plugin that do that which is called fold page list. Hope that helps.

  2. I got a hold of that plugin, but not quite sure how to keep the other non-used sections from displaying once you start drilling down into the nav. Yours is perfect. Any chance of getting a hint as to what the nav code is in your sidebar? Right now I have:
    Still looking around , but not finding anything 🙁

  3. Any idea if this is still working 0n 2.9? I am not able to get the different IDs for the page hierarchy. Without current_page_item or current_page_ancestor I can not set the different styles.
    The exact line I am using is: <?php wp_list_pages('&title_li=&link_before=&link_after=&depth=2′); ?>
    Any help will be much appreciated!
    Thanks,
    Paul

  4. Yes it is still valid and it will be in future too.
    First thing is a class not an id and make sure you target the right element.
    I would also simply check the source file to see if the class outputs correctly.

  5. Thanks Lucian, then I check the code I just see the default class class=”page_item page-item-(the number)” but nothing else. Also I see the span tags on parent and child.
    Do you have any idea what may be wrong?
    Thanks again,
    Paul

  6. You need to be inside a child page to see the parent ancestor class. You need to setup a child page in WordPress back-end, by assigning a parent page to it.
    I have just tested it and it works. Not sure what you are doing wrong.

  7. Hi, any idea why the ‘wp_list_page(post_type=xyz)’ does not produce any ‘current’ classes??
    I mean how can i css-style a current_page_item in a list of pages that are of a custom-post-type?
    Thanks in advance

  8. I don’t believe this is included in the core yet but there is a workaround.
    Assuming you use the custom navigation code to call the menu (the code uses the escaped php characters and need to be adjusted):
    ‘Main Menu’ )); ?>
    you can replace it with:
    ‘Main Menu’, ‘echo’ => false));
    // get post type
    $post_type = get_post_type( $post );
    if (preg_match(‘/custom-post-type-name-class/’, $nav_menu) && $post_type == ‘custom-post-type-name’) {
    $nav_menu = preg_replace(‘/class=”custom-post-type-name-class/’, ‘/class=”current_page_item /’, $nav_menu);
    }
    echo $nav_menu;
    ?>

  9. @Norbert The custom post type pages are not considered “pages” by the is_page() check, which is used in the wp_list_pages() to figure out current-… classes.
    Workaround for now is to set
    $wp_query->is_posts_page=true;
    or
    $wp_query->is_page=true;
    before calling wp_list_pages().
    If your code requires it, set whatever you changed back to false after getting your list.

  10. is it possible to get the to generate a class? if the list could generate the class equal to the page name i think that could be pretty powerful

  11. Nice! You seem to know how to manage the function wp_list_pages pretty well. So I’m asking you one question. Is it
    possible to customize the href in the link so it will add an ‘#’ at the beginning of the href ? I’m using a theme
    that used Anchors to scroll between pages.
    Thanks

  12. How can I check current page is home page or other.
    I try this syntax
    if ( is_home() ) { echo ‘ class=”current_page_item”‘; }
    But not working I use wordpress 3.3
    Any idea…???

Comments are closed.