In this tutorial I am going to show you how to do proper, full breadcrumbs in WordPress including nested categories and nested pages. Breadcrumbs are a pretty standard design pattern and can be very useful in a lot of website situations.

I’m aware there are already some good plugins for adding breadcrumbs in WordPress but I’m going to show you how to do it the good old fashioned way.

The PHP Code

Since I like to copy and paste I’ll post the full code first and then take a look at what it’s doing. You can just include this function in your theme’s “functions.php” file.


function get_breadcrumbs()
{
    global $wp_query;

    if ( !is_home() ){

        // Start the UL
        echo '<ul class="breadcrumbs">';
        // Add the Home link
        echo '<li><a href="'. get_settings('home') .'">'. get_bloginfo('name') .'</a></li>';

        if ( is_category() )
        {
            $catTitle = single_cat_title( "", false );
            $cat = get_cat_ID( $catTitle );
            echo "<li>  ". get_category_parents( $cat, TRUE, "  " ) ."</li>";
        }
        elseif ( is_archive() && !is_category() )
        {
            echo "<li>  Archives</li>";
        }
        elseif ( is_search() ) {

            echo "<li>  Search Results</li>";
        }
        elseif ( is_404() )
        {
            echo "<li>  404 Not Found</li>";
        }
        elseif ( is_single() )
        {
            $category = get_the_category();
            $category_id = get_cat_ID( $category[0]->cat_name );

            echo '<li>  '. get_category_parents( $category_id, TRUE, "  " );
            echo the_title('','', FALSE) ."</li>";
        }
        elseif ( is_page() )
        {
            $post = $wp_query->get_queried_object();

            if ( $post->post_parent == 0 ){

                echo "<li>  ".the_title('','', FALSE)."</li>";

            } else {
                $title = the_title('','', FALSE);
                $ancestors = array_reverse( get_post_ancestors( $post->ID ) );
                array_push($ancestors, $post->ID);

                foreach ( $ancestors as $ancestor ){
                    if( $ancestor != end($ancestors) ){
                        echo '<li>  <a href="'. get_permalink($ancestor) .'">'. strip_tags( apply_filters( 'single_post_title', get_the_title( $ancestor ) ) ) .'</a></li>';
                    } else {
                        echo '<li>  '. strip_tags( apply_filters( 'single_post_title', get_the_title( $ancestor ) ) ) .'</li>';
                    }
                }
            }
        }

        // End the UL
        echo "</ul>";
    }
}

We then include the following code on any pages you want breadcrumbs to appear:


<?php get_breadcrumbs(); ?>

The CSS Code

The CSS code is just adding some simple styling so that the links appear inline. This can be styled as you wish.


ul.breadcrumbs {
    list-style: none;
    padding: 0;
    margin: 0;
    font-size:12px;
}
ul.breadcrumbs li {
    float: left;
    margin: 0 5px 0 0;
    padding: 0;
}

The Explanation

So what are we doing here? Well lets start at the start.

  • First off don’t show breadcrumbs if it’s the homepage. If it’s not we add our first link which is to the top level homepage.
  • We then have a simple set of elseif statements which cover us for all the different situations we might find ourselves in. Some are fairly self explanatory like the seach, 404 and archive sections.
  • If it is a category we simply find the category ID then get list the parents of the current category. WordPress helps us with this by providing a “get_category_parents()” function.
  • If we are on a single page it gets a bit more in-depth. We have to find the category ID but in a slightly different way to above. However once you get the category ID it’s just the same method as above plus the addition of the title of the page you are on.

Now pages are slightly more in depth but nothing too complex:

  • First off get the page title. Easy.
  • We then find the ancestors of the page and reverse the order of them. Thankfully WordPress has a get_post_ancestors() function making our life much easier. The next line just adds the current post to the array of ancestors.
  • Finally we use a “foreach” loop to cycle through all of the ancestors and output them. The if statement in the loop makes sure that the last ancestor (the current page) doesn’t have a link.

So there you have it. Fully customizable, valid breadcrumbs in WordPress.