Хлебные крошки в WordPress без плагина: код и разметка
← Блог
WordPress · 03.10.2026 · 5 мин чтения

Хлебные крошки в WordPress без плагина: код и разметка

Хлебные крошки в WordPress показывают путь к странице: «Главная › Блог › Рубрика › Статья». По ним читатель может перейти в раздел или вернуться к списку записей.

Ниже — PHP-функция для классической темы, стили и JSON-LD-разметка BreadcrumbList. Если на сайте установлен Yoast SEO, сначала проверь его крошки: возможно, достаточно добавить их вывод в шаблон.

Хлебные крошки через Yoast SEO

Yoast SEO по умолчанию добавляет в JSON-LD страницы блок BreadcrumbList, даже если крошки не выводятся в шаблоне. Проверить можно в коде страницы: найди "@type":"BreadcrumbList". Если он есть, у тебя два пути:

  • Вывести крошки самого Yoast. Это упрощает согласование видимой цепочки со структурированными данными.
  • Написать свою функцию, как ниже, но без микроразметки Schema.org — второй BreadcrumbList на странице не нужен.

Вывод крошек Yoast в шаблоне, например в single.php перед заголовком:

<?php
if ( function_exists( 'yoast_breadcrumb' ) ) {
    yoast_breadcrumb( '<nav class="breadcrumbs" aria-label="Хлебные крошки">', '</nav>' );
}
?>

Названия звеньев и разделитель настраиваются в Yoast: «Настройки → Дополнительно → Хлебные крошки».

PHP-функция хлебных крошек без плагина

Функция собирает названия и ссылки в массив, а затем выводит список. В примере учтены записи, страницы, рубрики, поиск и страница 404. Добавь код в functions.php классической или дочерней темы:

function mytheme_breadcrumb_items() {
    $items = array(
        array( 'title' => 'Главная', 'url' => home_url( '/' ) ),
    );

    $blog_id = (int) get_option( 'page_for_posts' );
    $blog    = $blog_id ? array( 'title' => get_the_title( $blog_id ), 'url' => get_permalink( $blog_id ) ) : null;

    if ( is_singular( 'post' ) ) {
        if ( $blog ) {
            $items[] = $blog;
        }
        $categories = get_the_category();
        if ( $categories ) {
            $category = $categories[0];
            foreach ( array_reverse( get_ancestors( $category->term_id, 'category' ) ) as $parent_id ) {
                $items[] = array( 'title' => get_cat_name( $parent_id ), 'url' => get_category_link( $parent_id ) );
            }
            $items[] = array( 'title' => $category->name, 'url' => get_category_link( $category ) );
        }
        $items[] = array( 'title' => get_the_title(), 'url' => '' );
    } elseif ( is_page() ) {
        foreach ( array_reverse( get_post_ancestors( get_the_ID() ) ) as $parent_id ) {
            $items[] = array( 'title' => get_the_title( $parent_id ), 'url' => get_permalink( $parent_id ) );
        }
        $items[] = array( 'title' => get_the_title(), 'url' => '' );
    } elseif ( is_category() ) {
        if ( $blog ) {
            $items[] = $blog;
        }
        $term = get_queried_object();
        foreach ( array_reverse( get_ancestors( $term->term_id, 'category' ) ) as $parent_id ) {
            $items[] = array( 'title' => get_cat_name( $parent_id ), 'url' => get_category_link( $parent_id ) );
        }
        $items[] = array( 'title' => $term->name, 'url' => '' );
    } elseif ( is_home() && $blog ) {
        $items[] = array( 'title' => $blog['title'], 'url' => '' );
    } elseif ( is_search() ) {
        $items[] = array( 'title' => 'Поиск: ' . get_search_query( false ), 'url' => '' );
    } elseif ( is_404() ) {
        $items[] = array( 'title' => 'Страница не найдена', 'url' => '' );
    } else {
        $items[] = array( 'title' => wp_strip_all_tags( get_the_archive_title() ), 'url' => '' );
    }

    return $items;
}

function mytheme_breadcrumbs() {
    if ( is_front_page() ) {
        return;
    }

    $items = mytheme_breadcrumb_items();
    $last  = count( $items ) - 1;

    echo '<nav class="breadcrumbs" aria-label="Хлебные крошки"><ol class="breadcrumbs__list">';
    foreach ( $items as $index => $item ) {
        echo '<li class="breadcrumbs__item">';
        if ( $index === $last || ! $item['url'] ) {
            echo '<span aria-current="page">' . esc_html( $item['title'] ) . '</span>';
        } else {
            echo '<a href="' . esc_url( $item['url'] ) . '">' . esc_html( $item['title'] ) . '</a>';
        }
        echo '</li>';
    }
    echo '</ol></nav>';
}

Что учтено:

  • Если в «Настройках → Чтение» задана отдельная страница записей, она появится в цепочке. Как её настроить, описано в статье о блоге на отдельной странице.
  • Вложенные рубрики и страницы выводятся всей цепочкой родителей через get_ancestors() и get_post_ancestors().
  • У записи в нескольких рубриках берётся первая из возвращённых WordPress. Основную рубрику Yoast этот код не учитывает: для неё нужно изменить выбор рубрики или использовать крошки самого Yoast.
  • Текущая страница — не ссылка, а <span aria-current="page">.
  • Все названия и адреса экранируются при выводе. Для поиска get_search_query( false ) возвращает сырое значение, а esc_html() экранирует его один раз.

Вызови функцию в шаблонах, где нужны крошки: <?php mytheme_breadcrumbs(); ?>. Обычно это single.php, page.php, archive.php и search.php. Ссылки на рубрики и страницы строятся так же, как в статье о ссылках в WordPress.

CSS для цепочки навигации

.breadcrumbs__list {
  display: flex;
  flex-wrap: wrap;
  gap: 4px;
  margin: 0;
  padding: 0;
  list-style: none;
  font-size: 14px;
}

.breadcrumbs__item:not(:last-child)::after {
  content: "›";
  margin-left: 4px;
  color: #6b7280;
}

Разделитель добавлен через CSS, а flex-wrap переносит длинную цепочку на новую строку. Проверь результат на узком экране и со скринридером: CSS-содержимое может озвучиваться в зависимости от браузера и программы чтения.

Микроразметка BreadcrumbList без Yoast

Если SEO-плагин не создаёт BreadcrumbList, добавь JSON-LD из того же массива, что и видимые крошки. Так обе версии цепочки будут согласованы. При активном Yoast пример ниже пропускает вывод схемы.

function mytheme_breadcrumbs_schema() {
    if ( is_front_page() || defined( 'WPSEO_VERSION' ) ) {
        return;
    }

    $list = array();
    foreach ( mytheme_breadcrumb_items() as $index => $item ) {
        $element = array(
            '@type'    => 'ListItem',
            'position' => $index + 1,
            'name'     => html_entity_decode( wp_strip_all_tags( $item['title'] ), ENT_QUOTES, 'UTF-8' ),
        );
        if ( $item['url'] ) {
            $element['item'] = $item['url'];
        }
        $list[] = $element;
    }

    $schema = array(
        '@context'        => 'https://schema.org',
        '@type'           => 'BreadcrumbList',
        'itemListElement' => $list,
    );

    echo '<script type="application/ld+json">' . wp_json_encode( $schema, JSON_UNESCAPED_UNICODE | JSON_HEX_TAG ) . '</script>';
}
add_action( 'wp_head', 'mytheme_breadcrumbs_schema' );

Для последнего звена Google разрешает не указывать item: им считается текущая страница. HTML-сущности в названиях декодируются, а JSON_HEX_TAG защищает тег script от преждевременного закрытия.

Проверь страницу в тесте расширенных результатов Google. Валидная разметка помогает описать структуру сайта, но не гарантирует показ хлебных крошек в поиске.

Документация

Есть вопрос или дополнение?

Обсудить в Telegram

Добавить комментарий