Hi, I'm a web developer and blogger from Russia. My nickname is Dimox.
Sorry for my English, it's not my native. Read more about me and my blog.

Wordpress Breadcrumbs Without a Plugin

Wordpress Breadcrumbs Without a Plugin

Breadcrumbs is an important element of a web site navigation, which boosts his usability. Especially it concerns to a sites with a complex structure. Unfortunatelly, I don’t use breadcrumbs on my sites, may be because their structure is very simple or because I could not find a way of making breadcrumbs, suitable for me.

I have seen a different ways of a breadcrumbs implementation on WordPress sites, but not one of them I does not like, because all of them does not display a full chain of links. So I have created my version of WordPress breadcrumbs without a plugin.

Yes, there is a ready plugins for WordPress breadcrumbs, but I prefer to use a short code snippets, which doing the same.

Features of my version of WordPress breadcrumbs

  • Displays a full chain of links to the current page. For example, if the current post is in a second level category, so breadcrumbs will looks like this:

    Home » Category » Subcategory » Post Title

    But all, what I have seen, displays only such an option (excluding plugins):

    Home » Subcategory » Post Title

    The same applies to pages and subpages. For example, for a 3rd level page breadcrumbs will looks like this:

    Home » Page Level 1 » Page Level 2 » Page Level 3

  • Breadcrumbs is appearing on a following types of WordPress pages:

    • paged navigation (like sitename.com/page/2/);
    • category archive;
    • tag archive;
    • daily archive;
    • monthly archive;
    • yearly archive;
    • author archive;
    • single post page;
    • single page;
    • attachment page;
    • search results;
    • 404 error page.
  • adding a page number (if archive page is second or more);

  • custom symbol of delimiter;

  • custom text for a ‘Home’ link;

  • current crumb styling.

WordPress breadcrumbs function (last updated: 2013.01.04)

function dimox_breadcrumbs() {

	/* === OPTIONS === */
	$text['home']     = 'Home'; // text for the 'Home' link
	$text['category'] = 'Archive by Category "%s"'; // text for a category page
	$text['search']   = 'Search Results for "%s" Query'; // text for a search results page
	$text['tag']      = 'Posts Tagged "%s"'; // text for a tag page
	$text['author']   = 'Articles Posted by %s'; // text for an author page
	$text['404']      = 'Error 404'; // text for the 404 page

	$showCurrent = 1; // 1 - show current post/page title in breadcrumbs, 0 - don't show
	$showOnHome  = 0; // 1 - show breadcrumbs on the homepage, 0 - don't show
	$delimiter   = ' » '; // delimiter between crumbs
	$before      = '<span class="current">'; // tag before the current crumb
	$after       = '</span>'; // tag after the current crumb
	/* === END OF OPTIONS === */

	global $post;
	$homeLink = get_bloginfo('url') . '/';
	$linkBefore = '<span typeof="v:Breadcrumb">';
	$linkAfter = '</span>';
	$linkAttr = ' rel="v:url" property="v:title"';
	$link = $linkBefore . '<a' . $linkAttr . ' href="%1$s">%2$s</a>' . $linkAfter;

	if (is_home() || is_front_page()) {

		if ($showOnHome == 1) echo '<div id="crumbs"><a href="' . $homeLink . '">' . $text['home'] . '</a></div>';

	} else {

		echo '<div id="crumbs" xmlns:v="http://rdf.data-vocabulary.org/#">' . sprintf($link, $homeLink, $text['home']) . $delimiter;

		if ( is_category() ) {
			$thisCat = get_category(get_query_var('cat'), false);
			if ($thisCat->parent != 0) {
				$cats = get_category_parents($thisCat->parent, TRUE, $delimiter);
				$cats = str_replace('<a', $linkBefore . '<a' . $linkAttr, $cats);
				$cats = str_replace('</a>', '</a>' . $linkAfter, $cats);
				echo $cats;
			}
			echo $before . sprintf($text['category'], single_cat_title('', false)) . $after;

		} elseif ( is_search() ) {
			echo $before . sprintf($text['search'], get_search_query()) . $after;

		} elseif ( is_day() ) {
			echo sprintf($link, get_year_link(get_the_time('Y')), get_the_time('Y')) . $delimiter;
			echo sprintf($link, get_month_link(get_the_time('Y'),get_the_time('m')), get_the_time('F')) . $delimiter;
			echo $before . get_the_time('d') . $after;

		} elseif ( is_month() ) {
			echo sprintf($link, get_year_link(get_the_time('Y')), get_the_time('Y')) . $delimiter;
			echo $before . get_the_time('F') . $after;

		} elseif ( is_year() ) {
			echo $before . get_the_time('Y') . $after;

		} elseif ( is_single() && !is_attachment() ) {
			if ( get_post_type() != 'post' ) {
				$post_type = get_post_type_object(get_post_type());
				$slug = $post_type->rewrite;
				printf($link, $homeLink . '/' . $slug['slug'] . '/', $post_type->labels->singular_name);
				if ($showCurrent == 1) echo $delimiter . $before . get_the_title() . $after;
			} else {
				$cat = get_the_category(); $cat = $cat[0];
				$cats = get_category_parents($cat, TRUE, $delimiter);
				if ($showCurrent == 0) $cats = preg_replace("#^(.+)$delimiter$#", "$1", $cats);
				$cats = str_replace('<a', $linkBefore . '<a' . $linkAttr, $cats);
				$cats = str_replace('</a>', '</a>' . $linkAfter, $cats);
				echo $cats;
				if ($showCurrent == 1) echo $before . get_the_title() . $after;
			}

		} elseif ( !is_single() && !is_page() && get_post_type() != 'post' && !is_404() ) {
			$post_type = get_post_type_object(get_post_type());
			echo $before . $post_type->labels->singular_name . $after;

		} elseif ( is_attachment() ) {
			$parent = get_post($post->post_parent);
			$cat = get_the_category($parent->ID); $cat = $cat[0];
			$cats = get_category_parents($cat, TRUE, $delimiter);
			$cats = str_replace('<a', $linkBefore . '<a' . $linkAttr, $cats);
			$cats = str_replace('</a>', '</a>' . $linkAfter, $cats);
			echo $cats;
			printf($link, get_permalink($parent), $parent->post_title);
			if ($showCurrent == 1) echo $delimiter . $before . get_the_title() . $after;

		} elseif ( is_page() && !$post->post_parent ) {
			if ($showCurrent == 1) echo $before . get_the_title() . $after;

		} elseif ( is_page() && $post->post_parent ) {
			$parent_id  = $post->post_parent;
			$breadcrumbs = array();
			while ($parent_id) {
				$page = get_page($parent_id);
				$breadcrumbs[] = sprintf($link, get_permalink($page->ID), get_the_title($page->ID));
				$parent_id  = $page->post_parent;
			}
			$breadcrumbs = array_reverse($breadcrumbs);
			for ($i = 0; $i < count($breadcrumbs); $i++) {
				echo $breadcrumbs[$i];
				if ($i != count($breadcrumbs)-1) echo $delimiter;
			}
			if ($showCurrent == 1) echo $delimiter . $before . get_the_title() . $after;

		} elseif ( is_tag() ) {
			echo $before . sprintf($text['tag'], single_tag_title('', false)) . $after;

		} elseif ( is_author() ) {
	 		global $author;
			$userdata = get_userdata($author);
			echo $before . sprintf($text['author'], $userdata->display_name) . $after;

		} elseif ( is_404() ) {
			echo $before . $text['404'] . $after;
		}

		if ( get_query_var('paged') ) {
			if ( is_category() || is_day() || is_month() || is_year() || is_search() || is_tag() || is_author() ) echo ' (';
			echo __('Page') . ' ' . get_query_var('paged');
			if ( is_category() || is_day() || is_month() || is_year() || is_search() || is_tag() || is_author() ) echo ')';
		}

		echo '</div>';

	}
} // end dimox_breadcrumbs()

Simply paste this function into a functions.php file of your theme and then paste the following code in a place of your theme, where breadcrumbs must appearing:

<?php if (function_exists('dimox_breadcrumbs')) dimox_breadcrumbs(); ?>

All that remains to do for now, is to design your breadcrumbs with CSS. You can use #crumbs for styling breadcrumbs block and #crumbs .current for styling a current crumb.

You can also look at breadcrumbs video tutorial, which show you how to install this function on TwentyTen WordPress theme.

Function works on WordPress 3.0 or higher.

Cоmmеnts (525):
  1. 481

    It worked like a charm. You made my day.
    Thanx a ton :)

  2. 482

    Great function, but it doesn’t seem to work when using a custom page template. Any idea what the problem is?

  3. 483

    Scrap that! The call to the function hadn’t been added to the custom template! Doh!

    Many thanks, this is an excellent solution.

  4. 484

    Thanks for the code!

    I was hoping to excluded my blog posts and only have pages included. Is there a way that know of to do this?

    -Lee

  5. 486

    I’ve updated the function – added the support of schema.org rich snippets for breadcrumbs.

  6. 487

    Thanks for this function.

    When viewing the post, I don’t want the post title to show so I just add:
    if ( is_single()) $showCurrent = 0;

  7. 488

    When viewing an attachment, it throws an error:
    Notice: Undefined offset: 0

    If I remove/comment this code, the image will display find:
    elseif ( is_attachment() ) {
    $parent = get_post($post->post_parent);
    $cat = get_the_category($parent->ID); $cat = $cat[0];
    $cats = get_category_parents($cat, TRUE, $delimiter);
    $cats = str_replace('<a', $linkBefore . '<a' . $linkAttr, $cats);
    $cats = str_replace('', '' . $linkAfter, $cats);
    echo $cats;
    printf($link, get_permalink($parent), $parent->post_title);
    if ($showCurrent == 1) echo $delimiter . $before . get_the_title() . $after;
    }

    How can this be fixed?

  8. 489

    works like a charm! what a great time saver!

  9. 491

    Can you *please* provide a downloadable file for this function? It is a total pain to cut and paste this code! I want a *file* not code on the screen. :-(

    • 492

      With all due respect, I think that’s more than fair given the routine is provided for free! A simple “click – hold – drag” took just 2-3 seconds for me.

      • 493

        For me it was much harder — took a number of tries and it really sucked that when I did a ’save page as’, the code was massively peppered with ’s, so I couldn’t just pull the page itself into my text editor and extract the code that way. I did eventualy get the code, but it was a massive hassle — I ended up using two clicks — the second with ’shift’ — I could not drag since I kept overshooting the end of the code — I need to drag the pointer off the bottom of the window to get the screen to scroll down. Copy and paste is fine for *small* snippets (ones that fit completely on the screen), but for longer pieces of code, it is always better to have a downloadable file. I guess I just don’t have the hand-eye coordination. Partly it was my laptop, with its small screen.

  10. 496

    Thanks for the code, mate. One issue though I’d like to share:

    $cat = get_the_category(); will get categories in random order, so a parent and children categories can be wrong.

    In order to fix this, replace the line with

    $args = array('orderby' => 'id', 'order' => 'desc');
    $cat = wp_get_post_terms( $post->ID , 'category', $args);

  11. 497
    @
    Jessica said:

    Hi there,
    I love this plugin so much, but when I paste the code into the function, everything is OK except the gallery in pages,
    I insert the gallery in posts, they attachment page is OK,
    but when I click the attachment the page, it get errors:

    Object of class WP_Error could not be converted to string in

    } elseif ( is_page() && $post->post_parent ) {

  12. 498

    I want to hide the breadcrumb for date based archive only. How can I do it? What line do I have to change to do that or to create an option?
    Personally I dislike the date based archive.
    I’m sorry and thanks.

  13. 499

    May be a simple edit I’m missing, but I’m working in a custom css Wordpress that I didn’t create and I need to center the breadcrumb. How to do this?

  14. 501

    3.5.1 picture page display garbled!

  15. 502

    I’m here to say thank you for your tutorial. This tutorial had help our site build a better breadcrumb. Looking for more tutorial from you.
    Thank you once again.

  16. 503
    @
    LameFork said:

    It seems to have issues with pages that use pagination. Instead of being HOME » CONTENT » BLOG » PAGE 2, it comes out HOME » CONTENT » BLOGPAGE 2

  17. 504

    Hi,
    great function, really nice work. It works well, except I got this error:

    Catchable fatal error: Object of class WP_Error could not be converted to string

    on line

    echo get_category_parents($cat, TRUE, ‘ ‘ . $delimiter . ‘ ‘);


    Any ideas ?

  18. 506

    Possible to remove the hyperlinks for all level ?

    Thanks

  19. 508

    it’s really nice function!

  20. 509

    Would be great if you also provide some of CSS design options…
    Thanks.

  21. 510

    For anyone who wishes to hide the home crumb, a simple fix…

    add too Options section:

    $nohomecrumb = 1; // 1 - do not show crumb for home

    change the following:
    echo '' . sprintf($link, $homeLink, $text['home']) . $delimiter;

    to:


    if($nohomecrumb == 1) {
    echo '';
    } else {
    echo '' . sprintf($link, $homeLink, $text['home']) . $delimiter;
    }

  22. 511

    Thanks man, can I use this code in a commercial theme?

  23. 513

    beautiful! thanks for the helpful function. seo could be improved by setting the $before and $after tags to h1

  24. 514

    hi… i follow the instruction put in the code …
    the breadcrumbs should be look like this in formal way

    Home > Software Protection > Rockey 2

    but when i click the rockey 2 button it just only show

    Home > Rockey2

    How to get the solution on this …. any one can help?

  25. 516
    @
    Startx04 said:

    Hi Dimox,

    I have a question, not sure if you can answer it. My WP template use a modified version of your breadcrumbs code. I have some issues that the output is not correct. Unfortunately the seller of the template don’t give a s**t on supporting his stuff, so i need to figure the issue out on my own. I found in the code that the source was origin from you, so i, well… need some help and hope to find it here ^^
    Its a multilingual page (EN / JP) and the crumbs working fine in english but not in japanese. There the links beyond the displayed crumbs are correct, however the crumbs itself are only showing the “destination”, or the last page.

    The link to the specific page (didn’t do more yet since figured out this issue) is here:

    EN: (works) http://advantec-is.com/products/sonotron-ndt/isonic-utpod/?l=en
    JP: (wrong) http://advantec-is.com/products/sonotron-ndt/isonic-utpod/?l=ja

    Perhaps you can help me sorting that out, and i dont mind to donate for your support.

    Thanks in advance & best regards

    Startx04

    • 517
      @
      Startx04 said:

      …forgot… let me know what you need on further information..

    • 518

      Hi, I don’t understand what is the problem. I’m seeing full crumbs in both cases.

      • 519
        @
        Startx04 said:

        Thx for the quick response.

        Right, they are there but the japanese version shows:

        Home→ISONIC utPod→ISONIC utPod→ISONIC utPod

        while it should be:

        Home→Products→Sonotron NDT→ISONIC utPod

        (Apart from the issue that the japanese title in the crumbs is not displayed as it should, but thats another issue)

  26. 520
    @
    Startx04 said:

    Dimox, would you accept a job offer? I am thinking to send you my template and you help me fixing this issue.

    I am not able to fix that and really need some support on that. No time to change everything over to a new template at the moment..

    Give me a price and lets discuss. Let me know if you don’t want to support, then i need to look elsewhere since i cant fix that on my own.

    Thanks

  27. 521
    @
    tjcafferkey said:

    I’m getting error:
    Catchable fatal error: Object of class WP_Error could not be converted to string

    On line:
    $cat = get_the_category($parent->ID); $cat = $cat[0];

    Of:
    } elseif ( is_attachment() ) {
    $parent = get_post($post->post_parent);
    $cat = get_the_category($parent->ID); $cat = $cat[0];
    $cats = get_category_parents($cat, TRUE, $delimiter);
    $cats = str_replace('<a', $linkBefore . '<a' . $linkAttr, $cats);
    $cats = str_replace('', '' . $linkAfter, $cats);
    echo $cats;
    printf($link, get_permalink($parent), $parent->post_title);
    if ($showCurrent == 1) echo $delimiter . $before . get_the_title() . $after;

    Any ideas?

  28. 523

    Thank you very much for this great code!
    Daniel

  29. 524

    Thank you for this function.

    Any idea why the content marked up with RDFa is not valid in W3C?

  30. 525

    thank you very much ;)

Соmmеnt раgеs: « 1 ... 8 9 10
Lеаvе а Соmmеnt

© 2009–2013 Dimox.net  •  Privacy Policy