Vista-Like Breadcrumbs for WordPress

applevista-breadcrumbs2

Update: This was modified on February 10, 2015 to reflect changes in suggested calling code for Breadcrumb NavXT. Note that the Breadcrumb NavXT Multidimension Extensions plugin handles the PHP side of things covered in the guide below.

Update: This was modified on January 11, 2011 to reflect changes in the code base of Breadcrumb NavXT. Note that this should now work for all newer versions of Breadcrumb NavXT (3.6.0 up to 4.0). It will not work for the proposed Breadcrumb NavXT 4.0.

Previously, one revealed how to apply Janko’s Apple.com-like breadcrumb trail tutorial to WordPress using Breadcrumb NavXT. After several requests for a breadcrumb trail a la the one found in Explorer since Windows Vista, this guide was created. While this guide will not provide a method to exactly recreate the Vista breadcrumbs, it will be in the same spirit. The Apple.com breadcrumb trail style will be extended; a simple replacement of images and minor CSS tweaking will result something behaving very similar to the vista breadcrumb trail.

Download sources | View Demo

Before we begin, note that, unlike the Apple.com style breadcrumb guide, this one requires some PHP knowledge. Like the Apple.com style breadcrumb guide, the layout effects are pure CSS.
applevista-breadcrumbs3

Markup

While Breadcrumb NavXT is very flexible, and does almost anything out of the box, some things are not directly supported. For this guide, we need Breadcrumb NavXT to output something like:

<ul>
	<li><a href="#"><img src="images/home.png" alt="Home" /></a>
		<ul>
			<li><a href="#">Great Uncle Page 1</a></li>
			<li><a href="#">Great Aunt Page 1</a></li>
			<li><a href="#">Great Aunt Page 2</a></li>
		</ul>
	</li>
	<li><a href="#">Parent Page</a>
		<ul>
			<li><a href="#">Uncle Page 1</a></li>
			<li><a href="#">Aunt Page 1</a></li>
			<li><a href="#">Aunt Page 2</a></li>
			<li><a href="#">Uncle Page 2</a></li>
		</ul>
	</li>
	<li>Page
		<ul>
			<li><a href="#">Sibling Page 1</a></li>
			<li><a href="#">Sibling Page 2</a></li>
		</ul>
	</li>
</ul>

Natively, Breadcrumb NavXT, using the display_list function, for the same page, will output (note that the <ul> is not generated by Breadcrumb NavXT, but for completeness is shown here):

<ul>
	<li><a href="#"><img src="images/home.png" alt="Home" /></a></li>
	<li><a href="#">Parent Page</a></li>
	<li>Page</li>
</ul>

While the top level unordered list is correct, we need some depth (2nd order unordered list). To add this, we’ll use OOP inheritance to override the default behavior of the do_post_hierarchical and post_parents functions.

Open up the functions.php file for your theme. Within it we will create a new class named ext_breadcrumb_trail, and tell PHP that is an extension of the bcn_breadcrumb_trail class. At this time, the basic class constructor will be added as well.

class ext_breadcrumb_trail extends bcn_breadcrumb_trail
{
	//Default constructor
	function __construct()
	{
		//Need to make sure we call the constructor of bcn_breadcrumb_trail
		parent::__construct();
	}
}

Now, it is time to override bcn_breadcrumb_trail::page_parents. The default one does not check for siblings of the page. We need it to do this, and place these breadcrumbs in to the breadcrumb trail. While we could override the bcn_breadcrumb_trail::display_list function to accept multi dimensional breadcrumb trails, that is an exercise to be done at a later point in time. Instead, we’ll let WordPress’ wp_list_pages function help us out.

function post_parents($id, $frontpage)
{
	$parent = get_post($id);
	$suffix = '<ul>' . wp_list_pages('depth=1&child_of=' . $parent->post_parent . '&exclude=' . $parent->ID . '&echo=0&title_li=') . '</ul>';
	if($suffix !== '<ul></ul>')
	{
		$suffix = $this->opt['post_' . $parent->post_type . '_suffix'] . $suffix;
	}
	else
	{
		$suffix = $this->opt['post_' . $parent->post_type . '_suffix'];
	}
	//Place the breadcrumb in the trail
	$breadcrumb = $this->add(new bcn_breadcrumb(get_the_title($id), $this->opt['post_' . $parent->post_type . '_prefix'], $suffix));
	//Assign the anchor properties
	$breadcrumb->set_anchor($this->opt['post_' . $parent->post_type . '_anchor'], get_permalink($id));
	//Make sure the id is valid, and that we won't end up spinning in a loop
	if($parent->post_parent >= 0 && $parent->post_parent != false && $id != $parent->post_parent && $frontpage != $parent->post_parent)
	{
		//If valid, recursively call this function
		$this->post_parents($parent->post_parent, $frontpage);
	}
}

We tell wp_list_pages to grab only the children of the parent page, excluding the page found by post_parents. Then we cheat by setting this list as part of the breadcrumb suffix, to avoid having to override display_list.

 

Continuing on, we override bcn_breadcrumb_trail::do_post_hierarchical with a post_hierarchical modified in a similar fashion as post_parents.

function do_post_hierarchical()
{
	global $post;
	$suffix = '<ul>' . wp_list_pages('depth=1&child_of=' . $post->post_parent . '&exclude=' . $post->ID . '&echo=0&title_li=') . '</ul>';
	if($suffix !== '<ul></ul>')
	{
		$suffix = $this->opt['post_' . $post->post_type . '_suffix'] . $suffix;
	}
	else
	{
		$suffix = $this->opt['post_' . $post->post_type . '_suffix'];
	}
	//Place the breadcrumb in the trail
	$this->trail[] = new bcn_breadcrumb(get_the_title(), $this->opt['post_' . $post->post_type . '_prefix'], $suffix);
	//Done with the current item, now on to the parents
	$bcn_frontpage = get_option('page_on_front');
	//If there is a parent page let's find it
	if($post->post_parent && $post->ID != $post->post_parent && $bcn_frontpage != $post->post_parent)
	{
		$this->post_parents($post->post_parent, $bcn_frontpage);
	}
}

That’s all we need to do markup wise. While it is a bit hacked together, it requires less work on our part to implement. To call the new, extended breadcrumb trail use:

if(class_exists('ext_breadcrumb_trail'))
{
	//Make new instance of the ext_breadcrumb_trail object
	$breadcrumb_trail = new ext_breadcrumb_trail();
	//Setup options here if needed
	$breadcrumb_trail->opt['home_title'] = '<img src="' . get_bloginfo('template_directory') . '/images/home.png" alt="Home" />';
	//Fill the breadcrumb trail
	$breadcrumb_trail->fill();
	//Display the trail
	$breadcrumb_trail->display_list();
}

In this block of code the home title is also changed to the house icon image located in the activated theme’s /images/ directory. This wraps up the PHP/xHTML markup needed for this guide. The sources zip archive, link above, contains the ext_breadcrumb_trail class in a PHP file that is ready for linking.

 

Styling

Now that our markup is ready, we can style the unordered list. For this tutorial, one will be extending the styles from the Quick and Easy Apple.com Style Breadcrumb Trail for WordPress guide (reason being that it was already sitting around). This ends up being just a nice large blob of code, which can be downloaded here.

.breadcrumbs .home img
{
	border: none;
	margin: 9px 0px;
}

Going over it, per CSS selector, we first have the home image block that removes the border from the image and sets some appropriate margins.

.breadcrumbs
{
	font: 11px Arial, Helvetica, sans-serif;
	background: url('images/bc_bg.png') repeat-x;
	height: 30px;
	line-height: 30px;
	color: #9b9b9b;
	border: solid 1px #cacaca;
	width: 100%;
	overflow: hidden;
	margin: 0;
	padding: 0;
}

The main class selector sets some font properties, background image, border, height, and padding.

.breadcrumbs a
{
	text-decoration: none;
	color: #454545;
}

This styles all of the anchors, removing the underline and turning them a shade of gray.

.breadcrumbs > li > a
{
	height: 30px;
	display: block;
	background: url('images/bc_separator.png') right no-repeat;
	padding-right: 15px;
}

This sets the separator for all of the top level breadcrumb anchors. It adds in the breadcrumb separator and sets some padding.

.breadcrumbs a:hover
{
	color: #0088ff;
}

This causes any anchor in the breadcrumb trail to turn to a light blue color when hovered.

.breadcrumbs li
{
	list-style: none;
	margin: 0;
}

This causes all of the list elements in the breadcrumb trail to drop their bullet points and indent.

.breadcrumbs > li
{
	float: left;
	padding-left: 10px;
}

This causes the first level list elements to float right and have 10 pixels of padding on their left side.

.breadcrumbs li ul
{
	display: none;
	margin: 0 0 0 -18px;
	padding: 0;
}

This code hides the second level unordered lists from view, removes all padding, and shifts them 18 pixels to the left.

.breadcrumbs .home ul
{
	margin: 0 0 0 -11px;
}

This code is specific to the home breadcrumb; it shifts the second level list to the left by only 11 pixels.

.breadcrumbs li:hover ul
{
	display: block;
	position: absolute;
	border: solid 1px #cacaca;
	background: #fff;
}

This code causes the second level list to appear when its parent is hovered over. It also sets a border and background color to white.

.breadcrumbs li ul li
{
	padding: 0 10px;
}

This code causes all second level list elements to have 10 pixels of padding to the left and right.

Note that the images used as backgrounds in the CSS need to be located within your theme’s images directory. Also, in order to easily use the home image styling Breadcrumb NavXT 3.4 (or newer) is required.

-John Havlik

[end of transmission, stay tuned]

Trackbacks/Pingbacks

  1. Pingback: Use an Icon/Image for the Home Breadcrumb | mtekk's Crib

  2. Pingback: Breadcrumb NavXT Multi Dimension Extensions 1.6.0 | mtekk's Crib

13 thoughts on “Vista-Like Breadcrumbs for WordPress

  1. I have a custom theme. When I enable your breadcrumbs, and make the changes to my functions.php, my breadcrumb show like this:

    link1link2link3link4

    They work, but there are no “> separators, and the extended mouseover dropdowns don’t show.

    I know the breadcrumb works on it’s own as I can call that immediately before and it’ll work.

    What am I doing wrong?
    class ext_breadcrumb_trail extends bcn_breadcrumb_trail
    {
    //Default constructor
    function __construct()
    {
    //Need to make sure we call the constructor of bcn_breadcrumb_trail
    parent::__construct();
    }
    }

    function post_parents($id, $frontpage)
    {
    $parent = get_post($id);
    $suffix = '<ul>' . get_categories('depth=1&child_of=' . $parent->post_parent . '&exclude=' . $parent->ID . '&echo=0&title_li=') . '</ul>';
    if($suffix !== '<ul></ul>')
    {
    $suffix = $this->opt['post_' . $parent->post_type . '_suffix'] . $suffix;
    }
    else
    {
    $suffix = $this->opt['post_' . $parent->post_type . '_suffix'];
    }
    //Place the breadcrumb in the trail
    $breadcrumb = $this->add(new bcn_breadcrumb(get_the_title($id), $this->opt['post_' . $parent->post_type . '_prefix'], $suffix));
    //Assign the anchor properties
    $breadcrumb->set_anchor($this->opt['post_' . $parent->post_type . '_anchor'], get_permalink($id));
    //Make sure the id is valid, and that we won't end up spinning in a loop
    if($parent->post_parent >= 0 && $parent->post_parent != false && $id != $parent->post_parent && $frontpage != $parent->post_parent)
    {
    //If valid, recursively call this function
    $this->post_parents($parent->post_parent, $frontpage);
    }
    }
    function do_post_hierarchical()
    {
    global $post;
    $suffix = '<ul>' . wp_list_pages('depth=1&child_of=' . $post->post_parent . '&exclude=' . $post->ID . '&echo=0&title_li=') . '</ul>';
    if($suffix !== '<ul></ul>')
    {
    $suffix = $this->opt['post_' . $post->post_type . '_suffix'] . $suffix;
    }
    else
    {
    $suffix = $this->opt['post_' . $post->post_type . '_suffix'];
    }
    //Place the breadcrumb in the trail
    $this->trail[] = new bcn_breadcrumb(get_the_title(), $this->opt['post_' . $post->post_type . '_prefix'], $suffix);
    //Done with the current item, now on to the parents
    $bcn_frontpage = get_option('page_on_front');
    //If there is a parent page let's find it
    if($post->post_parent && $post->ID != $post->post_parent && $bcn_frontpage != $post->post_parent)
    {
    $this->post_parents($post->post_parent, $bcn_frontpage);
    }
    }

    <?php if(class_exists('ext_breadcrumb_trail'))
    {
    //Make new instance of the ext_breadcrumb_trail object
    $breadcrumb_trail = new ext_breadcrumb_trail();
    //Setup options here if needed
    $breadcrumb_trail->opt['home_title'] = '<img src="' . get_bloginfo('template_directory') . '/images/home.png" alt="Home" />';
    //Fill the breadcrumb trail
    $breadcrumb_trail->fill();
    //Display the trail
    $breadcrumb_trail->display_list(); } ?>

  2. Hey mtekk,

    this sounds like a great solution for a functionality (hybrid breadcrumbs/dropdown trail) which I have been looking for for a while. I am not a php wizard by any means but gave it a go anyway. Sadly, it did not turn out to be working for me.

    I am working with Breadcrumbs NavXT v3.8.1 in a custom theme (very basic) in WordPress v3.1.2. As shown in the Apple breadcrumbs trail article, the breadcrumbs are integrated as:

    <ul class="breadcrumb_trail">
    <?php
    if(function_exists('bcn_display_list'))
    {
    bcn_display_list();
    }
    ?>
    </ul>

    The functions.php in my theme folder looks like this:

    <?php

    class ext_breadcrumb_trail extends bcn_breadcrumb_trail
    {
    //Default constructor
    function __construct()
    {
    //Need to make sure we call the constructor of bcn_breadcrumb_trail
    parent::__construct();
    }
    }

    function post_parents($id, $frontpage)
    {
    $parent = get_post($id);
    $suffix = '<ul>' . wp_list_pages('depth=1&child_of=' . $parent->post_parent . '&exclude=' . $parent->ID . '&echo=0&title_li=') . '</ul>';
    if($suffix !== '<ul></ul>')
    {
    $suffix = $this->opt['post_' . $parent->post_type . '_suffix'] . $suffix;
    }
    else
    {
    $suffix = $this->opt['post_' . $parent->post_type . '_suffix'];
    }
    //Place the breadcrumb in the trail
    $breadcrumb = $this->add(new bcn_breadcrumb(get_the_title($id), $this->opt['post_' . $parent->post_type . '_prefix'], $suffix));
    //Assign the anchor properties
    $breadcrumb->set_anchor($this->opt['post_' . $parent->post_type . '_anchor'], get_permalink($id));
    //Make sure the id is valid, and that we won't end up spinning in a loop
    if($parent->post_parent >= 0 && $parent->post_parent != false && $id != $parent->post_parent && $frontpage != $parent->post_parent)
    {
    //If valid, recursively call this function
    $this->post_parents($parent->post_parent, $frontpage);
    }
    }

    function do_post_hierarchical()
    {
    global $post;
    $suffix = '<ul>' . wp_list_pages('depth=1&child_of=' . $post->post_parent . '&exclude=' . $post->ID . '&echo=0&title_li=') . '</ul>';
    if($suffix !== '<ul></ul>')
    {
    $suffix = $this->opt['post_' . $post->post_type . '_suffix'] . $suffix;
    }
    else
    {
    $suffix = $this->opt['post_' . $post->post_type . '_suffix'];
    }
    //Place the breadcrumb in the trail
    $this->trail[] = new bcn_breadcrumb(get_the_title(), $this->opt['post_' . $post->post_type . '_prefix'], $suffix);
    //Done with the current item, now on to the parents
    $bcn_frontpage = get_option('page_on_front');
    //If there is a parent page let's find it
    if($post->post_parent && $post->ID != $post->post_parent && $bcn_frontpage != $post->post_parent)
    {
    $this->post_parents($post->post_parent, $bcn_frontpage);
    }
    }

    if(class_exists('ext_breadcrumb_trail'))
    {
    //Make new instance of the ext_breadcrumb_trail object
    $breadcrumb_trail = new ext_breadcrumb_trail();
    //Setup options here if needed
    $breadcrumb_trail->opt['home_title'] = '<img src="' . get_bloginfo('template_directory') . '/images/home.png" alt="Home" />';
    //Fill the breadcrumb trail
    $breadcrumb_trail->fill();
    //Display the trail
    $breadcrumb_trail->display_list();
    }

    ?>

    This results in a second Home-link (unstyled, list-bulleted) appearing in the top left corner in addition to the breadcrumbs trail but no working dropdowns. Also, I am not sure where to place the ext_breadcrumb_navxt.php file exactly. Any suggestions how to get this working would be appreciated!

    Thanks in advance!
    – Kenji

  3. Hey John..is this an option in 4.1 now? You mentioned it won’t work in 4.0+ (i’m on 4.1) so I was just curious if you added it as an option.

  4. Can anyone please post a proper tutorial on how to use “Breadcrumb NavXT Multidim Extension plugin”. Such as where do we copy the file and how to enable it.

    • Robert,

      Once I get a little more time I’ll be revamping this guide and will cover using the Mulitdim Extension plugin there. Until then, you just need to download the file (linked above) and place it into your plugins folder. Then activate and call bcn_display_list_multidim() rather than bcn_display().

      -John Havlik

  5. I really like the multidim and am so looking for a plugin like this – I’ve tried following the instructions you give and i think I’ve got it working, its just the styling – any possibility you could give me the most basic of styling I would use to get this working – at the moment I have no clue what to do – I downloaded the other files you made available and used the code from the included stylesheet (applevista) from there but its not making any difference for from me.

    Also would this be correct ? … or di I have to change that first instance of bcn_display too?

    <?php if(function_exists('bcn_display'))
    {
    bcn_display_list_multidim();
    }?>

    What i did was remove this :
    my themes default breadcrumb generator is comment out

    <?php //echo theme_generator('breadcrumbs',$post_id);?>
    <div class="breadcrumbs breadcrumbs">
    <?php if(function_exists('bcn_display'))
    {
    bcn_display_list_multidim();
    }?>
    </div>

    I could really do with some advice pse 🙂
    thanking you in advance

    • <?php if(function_exists('bcn_display'))
      {
      bcn_display_list_multidim();
      }?>

      Will work, though I suggest replacing the other instance of bcn_display with bcn_display_list_multidim() to prevent any errors from being displayed if the multidim function is not available for some reason.

      You should be able to follow the styling instructions above and get something to happen to the breadcrumb trail. You should be adding the styling to your theme’s style.css file. Beyond that, I don’t provide theming and styling support.

      -John Havlik

Leave a Reply

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