Хлебные крошки в 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. Валидная разметка помогает описать структуру сайта, но не гарантирует показ хлебных крошек в поиске.