Quick and Easy Apple.com Style Breadcrumb Trail for WordPress

Almost a year ago, Janko Jovanovic posted a guide on how a little xHTML and CSS can duplicate the Apple.com store breadcrumb trail. Today, I’m going to show you how to apply Janko’s code to WordPress using Breadcrumb NavXT.

Ok, now with the requirements. You’ll need a WordPress blog (everyone should be running 2.8.1 by now), and Breadcrumb NavXT 3.2.1 (or newer).

First up, the xHTML. We are going to use the function bcn_display_list(), which was introduced in Breadcrumb NavXT 3.2.0. This will output a breadcrumb trail in list form. It is worth noting that bcn_display_list() does not output a <ul> or <ol> tag, those must be added around the calling function. We want to wrap the code with <ul> tags.

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

Place this code where you want the breadcrumb trail to show up, I recommend placing it in your theme’s header.php file. That is all the xHTML work that we need to do. Now, on to the CSS. Open up your theme’s style.css file. We’ll start with styling the <ul>.

.breadcrumb_trail { 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:0px; padding:0px; }

Line by line this is setting the font to the Arial/Helvetica family at the 11px size for the breadcrumb trail. Then, we set the background to an image and will repeat it horizontally across the screen. We set the height to 30 pixels for the unordered list and all text within it. This is because the background image is 30 pixels high, and the second will allow the text to be centered vertically without extra work. We set the text color to a shade of grey, this ends up being just the color of the current item breadcrumb text. We set the boarder to be 1 pixel high and a dark shade of grey in color. Next, the width of the unordered list element is set to be 100% of its containing element. We don’t want the trail to ever go outside of the preallocated area for the list, so we tell the browser to hide any overflowing content. Finally, we zero out the margin and padding.

Next we should get rid of those ugly bullet points next to each breadcrumb. Add the following code in below the code we just placed in the style.css file.

.breadcrumb_trail li { list-style:none; float:left; padding-left:10px; } 

This code will remove the bullet points next to each breadcrumb, cause the breadcrumbs to line in order from left to right and to keep 10 pixels of padding between each of them. Next, let’s style up those anchors (links).

.breadcrumb_trail a { height:30px; display:block; background:url('images/bc_separator.png') right no-repeat; padding-right: 15px; text-decoration: none; color:#454545; } 

Line by line this code will set the anchor height to 30 pixels. The anchors will be treated as block elements rather than inline elements. A background image will be used as our breadcrumb separator, we’ll set it to show up to the right of the anchor. We’ll allow 15 pixels to the right of each anchor so that the separator image displays properly. The normal anchor underline is removed, and finally we set the text color to a darkish gray.

Now we have a few, very short blocks of CSS styling for the hover condition on the anchor and the home breadcrumb icon.

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

When the anchors are hovered over this code will set the color of the anchor to a color similar to teal.

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

This centers the home icon vertically within the home breadcrumb. Now, save your style.css file.

Time to change a few settings in the Breadcrumb NavXT page. If Breadcrumb NavXT is not already activated, activate it at this time. The next step is different depending on the version of Breadcrumb NavXT you are using.

  • For Breadcrumb NavXT versions prior to 4.0: Under the General tab in the Breadcrumb NavXT settings page, change the Home Title from “Home” to <img src="YOUR_BLOG_URL/wp-content/themes/YOUR_ACTIVE_THEME/images/home.png" alt="Home" />.
  • For Breadcrumb NavXT 4.x: Under the General tab in the Breadcrumb NavXT settings page, change the Home Template to <a class="%type%" title="Go to %title%." href="%link%"><img src="YOUR_BLOG_URL/wp-content/themes/YOUR_ACTIVE_THEME/images/home.png" alt="%title%" /></a> and the Home Template (Unlinked) to <img src="YOUR_BLOG_URL/wp-content/themes/YOUR_ACTIVE_THEME/images/home.png" alt="%title%" />.

Remember to replace YOUR_BLOG_URL with the URL for your blog, and YOUR_ACTIVE_THEME with the folder name for your currently active theme. Save the settings. Note: this will have to be changed every time you change themes. If you feel adventurous, you can directly access the bcn_breadcrumb_trail class, which will allow you to assign a dynamic Home Title.

Finally, download this archive with the three images, home.png, bc_seperator.png, and bc_bg.png (The home.png was replaced from Janko’s originals as I didn’t like it). Upload it to your current theme’s images directory. If this directory does not exist, make one and place the images in it. Now, you should have a breadcrumb trail that looks like that on Apple.com.

-John Havlik

[end of transmission, stay tuned]

Keep a Page Out of the Breadcrumb Trail

Note: This guide is only valid for versions of Breadcrumb NavXT prior to 4.0. Since Breadcrumb NavXT 4.0 the bcn_after_fill action should be used to remove breadcrumbs from the breadcrumb trail.

In the past, several users have asked how to exclude certain pages from the breadcrumb trail generated by Breadcrumb NavXT. As with most programming problems, many solutions exist to this problem. Previously, one posted code that removed the breadcrumb from the bcn_breadcrumb_trail::trail array before calling bcn_breadcrumb_trail::display(). However, since the introduction of Breadcrumb NavXT 3.0 a much better solution exists. This method uses the inheritance principle of OOP and requires no editing of the distributed files.

Code in this tutorial was written against the SVN Trunk version of Breadcrumb NavXT (the basis or Breadcrumb NavXT 3.3.0). Therefore, any code contained herein will require some modifications to work with Breadcrumb NavXT 3.2.x. The general process, however, is the same for any version of Breadcrumb NavXT since 3.0.0. Also, note that you must have a PHP5 environment for this to work as it requires the PHP5 object model.

First, open the functions.php file of your theme. Within it we are going to create a new class named ext_breadcrumb_trail, and tell PHP that it is an extension of the bcn_breadcrumb_trail class. We’ll place the skeleton for the class constructor in at this time 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();
	}
}

We need a way to get the IDs that will be excluded from the trail into the class. They could be hard coded into the class, but that is not very extensible (and a very bad coding practice). Instead, a public member variable named $excluded_ids will be added to store the IDs. Now, we should have the constructor accept IDs to exclude and store them in $excluded_ids. Our code now looks similar to the following:

class ext_breadcrumb_trail extends bcn_breadcrumb_trail
{
	public $excluded_ids = array();
	//Default constructor
	function __construct($excluded_ids)
	{
		//Set the value of
		$this->excluded_ids = $excluded_ids;
		//Need to make sure we call the constructor of bcn_breadcrumb_trail
		parent::__construct();
	}
}

Now that the IDs of pages to be excluded can get into the class, we need to do something with them. We want to override the function bcn_breadcrumb_trail::page_parents() since it does not know how to exclude pages. To start, we’ll copy the code for page_parents from the class bcn_breadcrumb_trail into our new class. This is the result:

class ext_breadcrumb_trail extends bcn_breadcrumb_trail
{
	public $excluded_ids = array();
	function __construct($excluded_ids)
	{
		$this->excluded_ids = $excluded_ids;
		parent::__construct();
	}
	/**
	 * page_parents
	 *
	 * A Breadcrumb Trail Filling Function
	 *
	 * This recursive functions fills the trail with breadcrumbs for parent pages.
	 * @param  (int)   $id The id of the parent page.
	 * @param  (int)   $frontpage The id of the front page.
	 */
	function page_parents($id, $frontpage)
	{
		$parent = get_post($id);
		//Place the breadcrumb in the trail, uses the constructor
		$breadcrumb = $this->add(new bcn_breadcrumb(apply_filters('the_title', $parent->post_title), $this->opt['page_prefix'], $this->opt['page_suffix']));
		//Assign the anchor properties
		$breadcrumb->set_anchor($this->opt['page_anchor'], get_permalink($id));
		//Make sure the id is valid
		if($parent->post_parent >= 0 && $parent->post_parent != false && $id != $parent->post_parent && $frontpage != $parent->post_parent)
		{
			//If valid, recursively call this function
			$this->page_parents($parent->post_parent, $frontpage);
		}
	}
}

Now, it’s time to modify the page_parents() function. We’ll use ext_breadcrumb_trail::excluded_ids and the PHP function in_array() to skip the breadcrumb insertion step for pages that are to be excluded from the trail. We do this by wrapping the two lines of code containing the variable $breadcrumb within a branch of an if statement. Within the if statement we’ll use $id and $this->excluded_ids as the parameters for in_array(). Since we want the branch to run if the ID is not an excluded ID, we’ll place the not operator (!) in front of in_array. At this point, we have the final version of our class that is ready to use.

class ext_breadcrumb_trail extends bcn_breadcrumb_trail
{
	public $excluded_ids = array();
	function __construct($excluded_ids)
	{
		$this->excluded_ids = $excluded_ids;
		parent::__construct();
	}
	/**
	 * page_parents
	 *
	 * A Breadcrumb Trail Filling Function
	 *
	 * This recursive functions fills the trail with breadcrumbs for parent pages.
	 * @param  (int)   $id The id of the parent page.
	 * @param  (int)   $frontpage The id of the front page.
	 */
	function page_parents($id, $frontpage)
	{
		$parent = get_post($id);
		//Check if the current page should be excluded
		if(!in_array($id, $this->excluded_ids))
		{
			//Place the breadcrumb in the trail, uses the constructor
			$breadcrumb = $this->add(new bcn_breadcrumb(apply_filters('the_title', $parent->post_title), $this->opt['page_prefix'], $this->opt['page_suffix']));
			//Assign the anchor properties
			$breadcrumb->set_anchor($this->opt['page_anchor'], get_permalink($id));
		}
		//Make sure the id is valid
		if($parent->post_parent >= 0 && $parent->post_parent != false && $id != $parent->post_parent && $frontpage != $parent->post_parent)
		{
			//If valid, recursively call this function
			$this->page_parents($parent->post_parent, $frontpage);
		}
	}
}

Next, we need to modify the breadcrumb trail calling code in the theme. Assuming that the theme directly calls the bcn_breadcrumb_trail class, very little has to be modified. We just replace all instances of bcn_breadcrumb_trail with ext_breadcrumb_trail in the calling code. Additionally, when creating the new instance of ext_breadcrumb_trail we need to feed in our array of IDs of pages to be excluded. An example calling code block is located below, in it pages with ID equal to 100, 230, or 231 will not show up in the breadcrumb trail except when they are the current page.

if(class_exists('ext_breadcrumb_trail'))
{
	//Make new instance of the ext_breadcrumb_trail object
	$breadcrumb_trail = new ext_breadcrumb_trail(array(100,230,231));
	//Setup options here if needed
	//Fill the breadcrumb trail
	$breadcrumb_trail->fill();
	//Display the trail
	$breadcrumb_trail->display();
}

In this tutorial we never modified any of the actual plugin files. This was made possible due to inheritance through the creation of a derived class. Since no plugin files were modified, upgrading to new versions of Breadcrumb NavXT are less likely to break the functionality. Finally, this method can easily be modified to exclude categories instead of pages from the breadcrumb trail (replace page_parents with category_parents).

-John Havlik

[end of transmission, stay tuned]