25% off ProSNIPC25OFF

Breadcrumbs Trail

Outputs a schema.org-marked-up breadcrumb trail for posts, pages, and archive pages without any plugin dependency.

Module2 parts · by SnipCraft

PHPLogic

php
<?php
if ( ! function_exists( 'scseed_breadcrumbs' ) ) {
    function scseed_breadcrumbs() {
        if ( is_front_page() ) { return; }

        $crumbs  = array();
        $crumbs[] = array( 'name' => __( 'Home', 'scseed' ), 'url' => home_url( '/' ) );

        if ( is_singular() ) {
            $post = get_queried_object();
            if ( $post && ! empty( $post->post_type ) ) {
                $post_type = get_post_type_object( $post->post_type );
                if ( $post_type && $post_type->has_archive && 'post' !== $post->post_type ) {
                    $crumbs[] = array(
                        'name' => esc_html( $post_type->label ),
                        'url'  => get_post_type_archive_link( $post->post_type ),
                    );
                }
                if ( 'post' === $post->post_type ) {
                    $cats = get_the_category( $post->ID );
                    if ( $cats ) {
                        $crumbs[] = array(
                            'name' => esc_html( $cats[0]->name ),
                            'url'  => get_category_link( $cats[0]->term_id ),
                        );
                    }
                }
            }
            if ( $post ) {
                $crumbs[] = array( 'name' => get_the_title( $post->ID ), 'url' => '' );
            }
        } elseif ( is_category() || is_tag() || is_tax() ) {
            $crumbs[] = array( 'name' => single_term_title( '', false ), 'url' => '' );
        } elseif ( is_post_type_archive() ) {
            $crumbs[] = array( 'name' => post_type_archive_title( '', false ), 'url' => '' );
        } elseif ( is_search() ) {
            $crumbs[] = array( 'name' => sprintf( __( 'Search: %s', 'scseed' ), get_search_query() ), 'url' => '' );
        }

        $list_items = '';
        $count      = count( $crumbs );
        foreach ( $crumbs as $i => $crumb ) {
            $pos     = $i + 1;
            $is_last = ( $i === $count - 1 );
            $link    = $is_last
                ? '<span itemprop="name">' . esc_html( $crumb['name'] ) . '</span>'
                : '<a itemprop="item" href="' . esc_url( $crumb['url'] ) . '"><span itemprop="name">' . esc_html( $crumb['name'] ) . '</span></a>';
            $list_items .= '<li itemprop="itemListElement" itemscope itemtype="https://schema.org/ListItem">' .
                           $link .
                           '<meta itemprop="position" content="' . esc_attr( $pos ) . '">' .
                           ( $is_last ? '' : '<span class="scseed-bc-sep" aria-hidden="true">/</span>' ) .
                           '</li>';
        }

        echo '<nav class="scseed-breadcrumbs" aria-label="' . esc_attr__( 'Breadcrumb', 'scseed' ) . '">' .
             '<ol itemscope itemtype="https://schema.org/BreadcrumbList">' .
             $list_items . '</ol></nav>';
    }
    add_action( 'scseed_breadcrumbs', 'scseed_breadcrumbs' );
    // Auto-inject above post content
    add_filter( 'the_content', function ( $content ) {
        if ( is_singular() && is_main_query() && in_the_loop() ) {
            ob_start();
            do_action( 'scseed_breadcrumbs' );
            return ob_get_clean() . $content;
        }
        return $content;
    }, 5 );
}

CSSStyles

css
.scseed-breadcrumbs {
  font-size: 0.82rem;
  margin-bottom: 1.25rem;
}
.scseed-breadcrumbs ol {
  list-style: none;
  padding: 0;
  margin: 0;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.25rem;
}
.scseed-breadcrumbs li {
  display: flex;
  align-items: center;
  gap: 0.25rem;
  color: #888;
}
.scseed-breadcrumbs a {
  color: #0073aa;
  text-decoration: none;
}
.scseed-breadcrumbs a:hover {
  text-decoration: underline;
}
.scseed-bc-sep {
  color: #bbb;
  user-select: none;
}
#frontend#ux#seo#navigation