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;
    • custom post type;
    • 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;

  • integrated Google structured data.

WordPress breadcrumbs function (last updated: 2015.05.21)

/*
 * WordPress Breadcrumbs
 * author: Dimox
 * version: 2015.05.21
*/
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
	$text['page']     = 'Page %s'; // text 'Page N'
	$text['cpage']    = 'Comment Page %s'; // text 'Comment Page N'

	$delimiter      = '›'; // delimiter between crumbs
	$delim_before   = '<span class="divider">'; // tag before delimiter
	$delim_after    = '</span>'; // tag after delimiter
	$show_home_link = 1; // 1 - show the 'Home' link, 0 - don't show
	$show_on_home   = 0; // 1 - show breadcrumbs on the homepage, 0 - don't show
	$show_current   = 1; // 1 - show current page title, 0 - don't show
	$show_title     = 1; // 1 - show the title for the links, 0 - don't show
	$before         = '<span class="current">'; // tag before the current crumb
	$after          = '</span>'; // tag after the current crumb
	/* === END OF OPTIONS === */

	global $post;
	$home_link      = home_url('/');
	$link_before    = '<span itemscope itemtype="http://data-vocabulary.org/Breadcrumb">';
	$link_after     = '</span>';
	$link_attr      = ' itemprop="url"';
	$link_in_before = '<span itemprop="title">';
	$link_in_after  = '</span>';
	$link           = $link_before . '<a href="%1$s"' . $link_attr . '>' . $link_in_before . '%2$s' . $link_in_after . '</a>' . $link_after;
	$frontpage_id   = get_option('page_on_front');
	$parent_id      = $post->post_parent;
	$delimiter      = ' ' . $delim_before . $delimiter . $delim_after . ' ';

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

		if ($show_on_home == 1) echo '<div class="breadcrumbs"><a href="' . $home_link . '">' . $text['home'] . '</a></div>';

	} else {

		echo '<div class="breadcrumbs">';
		if ($show_home_link == 1) echo sprintf($link, $home_link, $text['home']);

		if ( is_category() ) {
			$cat = get_category(get_query_var('cat'), false);
			if ($cat->parent != 0) {
				$cats = get_category_parents($cat->parent, TRUE, $delimiter);
				$cats = preg_replace("#^(.+)$delimiter$#", "$1", $cats);
				$cats = preg_replace('#<a([^>]+)>([^<]+)<\/a>#', $link_before . '<a$1' . $link_attr .'>' . $link_in_before . '$2' . $link_in_after .'</a>' . $link_after, $cats);
				if ($show_title == 0) $cats = preg_replace('/ title="(.*?)"/', '', $cats);
				if ($show_home_link == 1) echo $delimiter;
				echo $cats;
			}
			if ( get_query_var('paged') ) {
				$cat = $cat->cat_ID;
				echo $delimiter . sprintf($link, get_category_link($cat), get_cat_name($cat)) . $delimiter . $before . sprintf($text['page'], get_query_var('paged')) . $after;
			} else {
				if ($show_current == 1) echo $delimiter . $before . sprintf($text['category'], single_cat_title('', false)) . $after;
			}

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

		} elseif ( is_day() ) {
			if ($show_home_link == 1) echo $delimiter;
			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() ) {
			if ($show_home_link == 1) echo $delimiter;
			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() ) {
			if ($show_home_link == 1) echo $delimiter;
			echo $before . get_the_time('Y') . $after;

		} elseif ( is_single() && !is_attachment() ) {
			if ($show_home_link == 1) echo $delimiter;
			if ( get_post_type() != 'post' ) {
				$post_type = get_post_type_object(get_post_type());
				$slug = $post_type->rewrite;
				printf($link, $home_link . '/' . $slug['slug'] . '/', $post_type->labels->singular_name);
				if ($show_current == 1) echo $delimiter . $before . get_the_title() . $after;
			} else {
				$cat = get_the_category(); $cat = $cat[0];
				$cats = get_category_parents($cat, TRUE, $delimiter);
				if ($show_current == 0 || get_query_var('cpage')) $cats = preg_replace("#^(.+)$delimiter$#", "$1", $cats);
				$cats = preg_replace('#<a([^>]+)>([^<]+)<\/a>#', $link_before . '<a$1' . $link_attr .'>' . $link_in_before . '$2' . $link_in_after .'</a>' . $link_after, $cats);
				if ($show_title == 0) $cats = preg_replace('/ title="(.*?)"/', '', $cats);
				echo $cats;
				if ( get_query_var('cpage') ) {
					echo $delimiter . sprintf($link, get_permalink(), get_the_title()) . $delimiter . $before . sprintf($text['cpage'], get_query_var('cpage')) . $after;
				} else {
					if ($show_current == 1) echo $before . get_the_title() . $after;
				}
			}

		// custom post type
		} elseif ( !is_single() && !is_page() && get_post_type() != 'post' && !is_404() ) {
			$post_type = get_post_type_object(get_post_type());
			if ( get_query_var('paged') ) {
				echo $delimiter . sprintf($link, get_post_type_archive_link($post_type->name), $post_type->label) . $delimiter . $before . sprintf($text['page'], get_query_var('paged')) . $after;
			} else {
				if ($show_current == 1) echo $delimiter . $before . $post_type->label . $after;
			}

		} elseif ( is_attachment() ) {
			if ($show_home_link == 1) echo $delimiter;
			$parent = get_post($parent_id);
			$cat = get_the_category($parent->ID); $cat = $cat[0];
			if ($cat) {
				$cats = get_category_parents($cat, TRUE, $delimiter);
				$cats = preg_replace('#<a([^>]+)>([^<]+)<\/a>#', $link_before . '<a$1' . $link_attr .'>' . $link_in_before . '$2' . $link_in_after .'</a>' . $link_after, $cats);
				if ($show_title == 0) $cats = preg_replace('/ title="(.*?)"/', '', $cats);
				echo $cats;
			}
			printf($link, get_permalink($parent), $parent->post_title);
			if ($show_current == 1) echo $delimiter . $before . get_the_title() . $after;

		} elseif ( is_page() && !$parent_id ) {
			if ($show_current == 1) echo $delimiter . $before . get_the_title() . $after;

		} elseif ( is_page() && $parent_id ) {
			if ($show_home_link == 1) echo $delimiter;
			if ($parent_id != $frontpage_id) {
				$breadcrumbs = array();
				while ($parent_id) {
					$page = get_page($parent_id);
					if ($parent_id != $frontpage_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 ($show_current == 1) echo $delimiter . $before . get_the_title() . $after;

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

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

		} elseif ( is_404() ) {
			if ($show_home_link == 1) echo $delimiter;
			echo $before . $text['404'] . $after;

		} elseif ( has_post_format() && !is_singular() ) {
			if ($show_home_link == 1) echo $delimiter;
			echo get_post_format_string( get_post_format() );
		}

		echo '</div><!-- .breadcrumbs -->';

	}
} // end dimox_breadcrumbs()

Gist on GitHub.

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 .breadcrumbs for styling breadcrumbs block and .breadcrumbs .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 (635):
  1. 600
    @
    carlos said:

    Hi,

    Thank you so much for this code.

    I`v read all the comments and try to figure out how to have this:

    home>>CPT>>taxonomy_name>>child_taxonomy_name>>product_name

    Like this:

    Home>>products>>sony>>mp3 player>>MX DVZ

    Is it possible

    Thanks

  2. 601

    Hi Dimox,

    great work. Before I had a few problems with the Breadcrumb NavXT plugin but your code solved my problem. Less plugins – less trouble, thank you for that ;-)

    However, my website is a Multi-site network and I do have one little problem. On the jobs-board landing page page, if you click on a job it looks like that:
    You are here: Home » Job Listing » Early Childhood Teacher – Lismore
    If you want to go back to the parent page (job listings) it goes to an error 404 page or and if you do the same on another site of the website network it goes to http://jobshubnct.org.au/taree/job-applications/

    Could you please have a look?

    Thanks for your help
    Thomas

  3. 602

    Hi,

    Thanks for this great code. I have only one problem and it is when I hover the category link the title is ” View all posts in xxx ” – which xxx is the category name -. My question is how to make the link hover is only the category name? I will appreciate your answer very much.

    Thanks in advance,
    Mansour

    • 603

      Hi,

      Find this row (in 3 places):

      if ($show_title == 0) $cats = preg_replace('/ title="(.*?)"/', '', $cats);

      and paste the following after it:

      $cats = str_replace('View all posts in ', '', $cats);
  4. 605

    Hey,

    my problem is that the trail is working for all sites etc. But I have custom post types and they are all in german. So for example I have this right in german: home > zimmer > standard zimmer its correct! But in english it is: home > zimmer > standard room but i must be home > ROOMS > standard room When its like this iI always come back to german Zimmer not english “rooms”.

  5. 607

    Thanks for the tutorial, I try to implemented your tutorial in my next project using Twenty Twelve themes but got error,
    I put the at single.php and got error, and I try to put in header.php also got error. Any advise will be appreciate

    Regards
    Wayan Adika

  6. 608

    Thank you so much, Dimox. This is exactly what I was looking for.

    P.S.: Code is poetry!

  7. 609

    Hi, I have been using this code for a couple years and it has worked great but I have recently come to an issue with hierarchical custom post types.

    What I would like is for it to display: home > custom_post_type_name > post_parent > post
    but what is happening is it is not displaying the post parent, instead it shows as: home > custom_post_type_name > post

    I noticed one user posted this solution but they didn’t specify where in the code it is to go or if it’s replacing a snippet of code, it doesn’t appear to work where I think it is to go.

    Any help would be greatly appreciated.

  8. 610

    Hello,

    I want to display all submenu in breadcrums, for that what can i changed in code ?
    for example my menu: About ->team -> culture -> history

    so when i click on team breadcrums display like: You are here: About ->team -> culture -> history

  9. 613

    Hi,

    Nice snippet, tank you!

    I have a question, thou: Why I cannot use bloginfo(‘name’) instead of Home in
    $text[‘home’] = ‘Home'; // text for the ‘Home’ link

    It pushed the text outside the snippet.

    Thank you

  10. 615

    Hello!
    Thank you for the great snippet! I have one question: Is it possible to limit the breadcrumb length?

    Greetings
    Frank

  11. 619

    Hi Dimox
    Thank you kindly for this option.
    What would be the way to make current page clickable?
    The last entry in breadcrumbs.

  12. 621

    In search result, i got this mydomain.com > Home > News

    How to delete Home > ?

    I just want to like this mydomain.com > News

  13. 622

    I freaking love you for this, great job! Good code. Thanks

  14. 623
    @
    Millena said:

    Hi thank you very much for the codes! Really helped me. But i just need the parent page to appers.
    Home>page1>page2>post

    Page2 is parent of page1. Is it possible to apears also do page2 NOT only Home>page1>post

    Thank you

  15. 624

    Hi Dimox

    Breadcrumps are a big problem for wordpress. I will try to implement your code in one of my websites. I am not a programmer, that is why I want to ask you a question about pasting this function into function.php file. Where exactly I have to paste this code, for example at the top of the file or after all the file’s functions.

    Thank you in advance!

  16. 625

    I just saw your video tutorial how to implement the code. Thank you again!

  17. 627
    @
    Piyush said:

    Hi, nice snippet.Very useful for me, but i would like to know how to disable it on certain pages in my website..
    i tried like this
    .page-id-XX .breadcrumbs { display: none; }

    But its not effective..

  18. 631

    Wonderful piece of code: saved me a lot of time.
    Thank you very much!

  19. 632
    @
    Alessio Soggetti said:

    Hi,

    I’m experiencing a little problem.

    I set these categories in WP:

    – Prodotti

    — Alimentazione
    — — Gas
    — — Pellet
    — — Legna

    — Convezione
    — — Convezione Acqua Calda
    — — Convezione Aria Calda
    — — Convezione Naturale

    — Tipologia
    — — Accessori
    — — Camini
    — — Stufe

    But i’ve got different results:
    1. http://www.edilfire.it/prodotti/tipologia/camini/camino-pellet-convezione-naturale-02/
    2. http://www.edilfire.it/prodotti/tipologia/stufe/stufa-gas-convezione-acqua-calda-02/

    The first one is correct, the second is not: I think the problem is related to the alphabetical order since in this page the breadcrumbs structure changes and shows “Convezione” instead of “Stufe”.

    Can you tell me how to fix it?

Соmmеnt раgеs: « 1 10 11 12
Lеаvе а Соmmеnt

© 2009–2015 Dimox.net  •  Privacy Policy