Breadcrumbs are essential for enhancing user navigation on your website. They provide a clear path for visitors to understand their location within your site’s hierarchy. While there are several plugins available for adding breadcrumbs in WordPress, using custom code can be more efficient and lightweight. In this guide, I’ll show you how to create custom breadcrumbs without relying on additional plugins.
Table of Contents
First, open your WordPress theme’s functions.php file. You can find this file in your theme directory. Add the following custom code snippet to the file:
// Start SV Breadcrumbs
function sv_custom_breadcrumbs()
{
ob_start();
// Settings
$separator = '>';
$breadcrums_id = 'sv_custom_breadcrumbs';
$breadcrums_class = 'sv_custom_breadcrumbs';
$home_title = 'Home';
// If you have any custom post types with custom taxonomies, put the taxonomy name below (e.g. product_cat)
$custom_taxonomy = 'product_cat';
// Get the query & post information
global $post, $wp_query;
// Do not display on the homepage
if (!is_front_page()) {
// Build the breadcrums
echo '<div id="' . $breadcrums_id . '" class="' . $breadcrums_class . '">';
if (is_search()) {
echo '<h2><strong>' . get_search_query() . '</strong></h2> <br />';
} else {
echo '<h2><strong>' . get_the_title() . '</strong></h2> <br />';
}
echo '<ul>';
// Home page
echo '<li class="item-home"><a class="bread-link bread-home" href="' . get_home_url() . '" >' . $home_title . '</a></li>';
// echo '<li class="separator separator-home"> ' . $separator . ' </li>';
if (is_archive() && !is_tax() && !is_category() && !is_tag()) {
echo '<li class="item-current item-archive"><h2><strong class="bread-current bread-archive">' . post_type_archive_title('', false) . '</strong></h2></li>';
} else if (is_archive() && is_tax() && !is_category() && !is_tag()) {
// If post is a custom post type
$post_type = get_post_type();
// If it is a custom post type display name and link
if ($post_type != 'post') {
$post_type_object = get_post_type_object($post_type);
$post_type_archive = get_post_type_archive_link($post_type);
echo '<li class="item-cat item-custom-post-type-' . $post_type . '"><a class="bread-cat bread-custom-post-type-' . $post_type . '" href="' . $post_type_archive . '" title="' . $post_type_object->labels->name . '">' . $post_type_object->labels->name . '</a></li>';
// echo '<li class="separator"> ' . $separator . ' </li>';
}
$custom_tax_name = get_queried_object()->name;
echo '<li class="item-current item-archive"><h2><strong class="bread-current bread-archive">' . $custom_tax_name . '</strong></h2></li>';
} else if (is_single()) {
// If post is a custom post type
$post_type = get_post_type();
// If it is a custom post type display name and link
if ($post_type != 'post') {
$post_type_object = get_post_type_object($post_type);
$post_type_archive = get_post_type_archive_link($post_type);
echo '<li class="item-cat item-custom-post-type-' . $post_type . '"><a class="bread-cat bread-custom-post-type-' . $post_type . '" href="' . $post_type_archive . '" title="' . $post_type_object->labels->name . '">' . $post_type_object->labels->name . '</a></li>';
// echo '<li class="separator"> ' . $separator . ' </li>';
}
// If it's a custom post type within a custom taxonomy
$taxonomy_exists = taxonomy_exists($custom_taxonomy);
if (empty($last_category) && !empty($custom_taxonomy) && $taxonomy_exists) {
$taxonomy_terms = get_the_terms($post->ID, $custom_taxonomy);
$cat_id = $taxonomy_terms[0]->term_id;
$cat_nicename = $taxonomy_terms[0]->slug;
$cat_link = get_term_link($taxonomy_terms[0]->term_id, $custom_taxonomy);
$cat_name = $taxonomy_terms[0]->name;
}
// Check if the post is in a category
if (!empty($last_category)) {
// echo $cat_display;
echo '<li class="item-current item-' . $post->ID . '"><h2><strong class="bread-current bread-' . $post->ID . '" title="' . get_the_title() . '">' . get_the_title() . '</strong></h2></li>';
// Else if post is in a custom taxonomy
} else if (!empty($cat_id)) {
echo '<li class="item-cat item-cat-' . $cat_id . ' item-cat-' . $cat_nicename . '"><a class="bread-cat bread-cat-' . $cat_id . ' bread-cat-' . $cat_nicename . '" href="' . $cat_link . '" title="' . $cat_name . '">' . $cat_name . '</a></li>';
// echo '<li class="separator"> ' . $separator . ' </li>';
echo '<li class="item-current item-' . $post->ID . '"><h2><strong class="bread-current bread-' . $post->ID . '" title="' . get_the_title() . '">' . get_the_title() . '</strong></h2></li>';
} else {
echo '<li class="item-current item-' . $post->ID . '"><h2><strong class="bread-current bread-' . $post->ID . '" title="' . get_the_title() . '">' . get_the_title() . '</strong></h></li>';
}
} else if (is_category()) {
// Category page
echo '<li class="item-current item-cat"><h2><strong class="bread-current bread-cat">' . single_cat_title('', false) . '</strong></h2></li>';
} else if (is_page()) {
// Standard page
if ($post->post_parent) {
// If child page, get parents
$anc = get_post_ancestors($post->ID);
// Get parents in the right order
$anc = array_reverse($anc);
// Parent page loop
if (!isset($parents))
$parents = null;
foreach ($anc as $ancestor) {
$parents .= '<li class="item-parent item-parent-' . $ancestor . '"><a class="bread-parent bread-parent-' . $ancestor . '" href="' . get_permalink($ancestor) . '" >' . get_the_title($ancestor) . '</a></li>';
// $parents .= '<li class="separator separator-' . $ancestor . '"> ' . $separator . ' </li>';
}
// Display parent pages
echo $parents;
// Current page
echo '<li class="item-current item-' . $post->ID . '"><h2><strong title="' . get_the_title() . '"> ' . get_the_title() . '</strong></h2></li>';
} else {
// Just display current page if not parents
echo '<li class="item-current item-' . $post->ID . '"><h2><strong class="bread-current bread-' . $post->ID . '"> ' . get_the_title() . '</strong></h2></li>';
}
} else if (is_tag()) {
// Tag page
// Get tag information
$term_id = get_query_var('tag_id');
$taxonomy = 'post_tag';
$args = 'include=' . $term_id;
$terms = get_terms($taxonomy, $args);
$get_term_id = $terms[0]->term_id;
$get_term_slug = $terms[0]->slug;
$get_term_name = $terms[0]->name;
// Display the tag name
echo '<li class="item-current item-tag-' . $get_term_id . ' item-tag-' . $get_term_slug . '"><h2><strong class="bread-current bread-tag-' . $get_term_id . ' bread-tag-' . $get_term_slug . '">' . $get_term_name . '</strong></h2></li>';
} elseif (is_day()) {
// Day archive
// Year link
echo '<li class="item-year item-year-' . get_the_time('Y') . '"><a class="bread-year bread-year-' . get_the_time('Y') . '" href="' . get_year_link(get_the_time('Y')) . '" title="' . get_the_time('Y') . '">' . get_the_time('Y') . ' Archives</a></li>';
// echo '<li class="separator separator-' . get_the_time('Y') . '"> ' . $separator . ' </li>';
// Month link
echo '<li class="item-month item-month-' . get_the_time('m') . '"><a class="bread-month bread-month-' . get_the_time('m') . '" href="' . get_month_link(get_the_time('Y'), get_the_time('m')) . '" title="' . get_the_time('M') . '">' . get_the_time('M') . ' Archives</a></li>';
// echo '<li class="separator separator-' . get_the_time('m') . '"> ' . $separator . ' </li>';
// Day display
echo '<li class="item-current item-' . get_the_time('j') . '"><h2><strong class="bread-current bread-' . get_the_time('j') . '"> ' . get_the_time('jS') . ' ' . get_the_time('M') . ' Archives</strong></h2></li>';
} else if (is_month()) {
// Month Archive
// Year link
echo '<li class="item-year item-year-' . get_the_time('Y') . '"><a class="bread-year bread-year-' . get_the_time('Y') . '" href="' . get_year_link(get_the_time('Y')) . '" title="' . get_the_time('Y') . '">' . get_the_time('Y') . ' Archives</a></li>';
// echo '<li class="separator separator-' . get_the_time('Y') . '"> ' . $separator . ' </li>';
// Month display
echo '<li class="item-month item-month-' . get_the_time('m') . '"><h2><strong class="bread-month bread-month-' . get_the_time('m') . '" title="' . get_the_time('M') . '">' . get_the_time('M') . ' Archives</strong></h2></li>';
} else if (is_year()) {
// Display year archive
echo '<li class="item-current item-current-' . get_the_time('Y') . '"><h2><strong class="bread-current bread-current-' . get_the_time('Y') . '" title="' . get_the_time('Y') . '">' . get_the_time('Y') . ' Archives</strong></h2></li>';
} else if (is_author()) {
// Auhor archive
// Get the author information
global $author;
$userdata = get_userdata($author);
// Display author name
echo '<li class="item-current item-current-' . $userdata->user_nicename . '"><h2><strong class="bread-current bread-current-' . $userdata->user_nicename . '" title="' . $userdata->display_name . '">' . 'Author: ' . $userdata->display_name . '</strong></h2></li>';
} else if (get_query_var('paged')) {
// Paginated archives
echo '<li class="item-current item-current-' . get_query_var('paged') . '"><h2><strong class="bread-current bread-current-' . get_query_var('paged') . '" title="Page ' . get_query_var('paged') . '">' . __('Page') . ' ' . get_query_var('paged') . '</strong></h2></li>';
} else if (is_search()) {
// Search results page
echo '<li class="item-current "><h2><strong class="bread-current " title="Search results for: ' . get_search_query() . '">Search results for: ' . get_search_query() . '</strong></h2></li>';
} elseif (is_404()) {
// 404 page
echo '<li>' . 'Error 404' . '</li>';
}
echo '</ul>';
echo '</div>';
}
$breadcrums = ob_get_clean();
return $breadcrums;
}
add_shortcode('sv-breadcrumbs', 'sv_custom_breadcrumbs');
// End SV Breadcrumbs
.custom_breadcrumbs {
list-style: none;
padding: 0;
margin: 0;
}
.custom_breadcrumbs li {
display: inline-block;
}
.custom_breadcrumbs li a {
text-decoration: none;
color: #333;
padding: 5px 10px;
}
.custom_breadcrumbs li a:hover {
color: #000;
}
.custom_breadcrumbs li:after {
content: ">";
padding: 0 5px;
color: #ccc;
}
.custom_breadcrumbs li:last-child:after {
content: "";
}
Now that you’ve added the custom code, you can display the breadcrumbs on your website. There are two methods to achieve this:
If you want to display breadcrumbs within your posts or pages, use the [sv-breadcrumbs] shortcode. Simply insert this shortcode where you want the breadcrumb trail to appear.
For more flexibility, you can directly call the sv_custom_breadcrumbs() function in your theme files. For instance, add the following code snippet to your template files (e.g., header.php, single.php, etc.):
echo sv_custom_breadcrumbs();
By following these steps, you can create custom breadcrumbs tailored to your website’s structure. Remember that well-implemented breadcrumbs not only improve user experience but also enhance your site’s SEO. Happy coding!
Feel free to customize the code further based on your specific requirements. If you have any questions or need additional assistance, feel free to ask! 😊