Главная/Статьи/Битрикс: настройка хлебных крошек (bitrix:breadcrumb)

Битрикс: настройка хлебных крошек (bitrix:breadcrumb)

Полное руководство по компоненту навигационной цепочки. Кастомизация, отключение на главной, микроразметка Schema.org.

ДМ
Дмитрий Мещеряков
📅 13 февраля 2019 г.📖 6 мин чтения

Хлебные крошки — тот случай, когда компонент выглядит примитивно, а вопросы к нему приходят годами: «почему на главной висит одинокая „Главная“», «почему в цепочке появился раздел, которого нет в меню», «почему Google не видит разметку». Все три вопроса решаются на уровне шаблона и правильного понимания того, откуда компонент вообще берёт данные.

Ключевой момент: bitrix:breadcrumb ничего не строит сам. Он лишь выводит цепочку, которую до него наполнили — компоненты (catalog.element добавляет товар), файлы .section.php и прямые вызовы AddChainItem. Отсюда следует главное правило отладки: если в крошках не то, чинить нужно не шаблон компонента, а того, кто добавил лишний пункт.

Базовое подключение

В файле header.php шаблона сайта:

php
<?php $APPLICATION->IncludeComponent(
    "bitrix:breadcrumb",
    "",  // Имя шаблона (пусто = default)
    [
        "START_FROM" => "0",
        "PATH" => "",
        "SITE_ID" => SITE_ID,
    ]
); ?>

Параметры компонента

ПараметрОписаниеЗначение по умолчанию
START_FROMНомер пункта, с которого строить цепочку0 (с корня)
PATHПуть для построения цепочкиТекущий путь
SITE_IDID сайтаТекущий сайт

Скрытие на главной странице

php
<?php if ($APPLICATION->GetCurPage(false) !== '/'): ?>
    <?php $APPLICATION->IncludeComponent(
        "bitrix:breadcrumb",
        "custom",
        [
            "START_FROM" => "0",
            "PATH" => "",
            "SITE_ID" => SITE_ID,
        ]
    ); ?>
<?php endif; ?>

Альтернативный способ:

php
<?php
$curPage = $APPLICATION->GetCurPage(false);
$isHomePage = ($curPage === '/' || $curPage === '/index.php');

if (!$isHomePage) {
    $APPLICATION->IncludeComponent("bitrix:breadcrumb", "custom", [
        "START_FROM" => "0",
    ]);
}
?>
💡 Совет

Почему скрывать крошки на главной — правильно. Навигационная цепочка из одного элемента не несёт информации, а в разметке BreadcrumbList с единственным пунктом Google не видит смысла и в выдаче её не покажет. Кроме того, ссылка «Главная», ведущая на текущую страницу, — лишний самореферентный линк.

Кастомный шаблон

Создайте шаблон в /local/templates/ШАБЛОН_САЙТА/components/bitrix/breadcrumb/custom/:

template.php

php
<?php if (!defined("B_PROLOG_INCLUDED") || B_PROLOG_INCLUDED !== true) die();

// $arResult содержит цепочку навигации
if (empty($arResult)) {
    return;
}
?>

<nav class="breadcrumb" aria-label="Навигация">
    <ol class="breadcrumb__list" itemscope itemtype="https://schema.org/BreadcrumbList">
        <?php foreach ($arResult as $index => $item): ?>
            <?php $isLast = ($index === count($arResult) - 1); ?>
            
            <li class="breadcrumb__item" itemprop="itemListElement" itemscope itemtype="https://schema.org/ListItem">
                <?php if (!$isLast && !empty($item['LINK'])): ?>
                    <a href="<?= $item['LINK'] ?>" class="breadcrumb__link" itemprop="item">
                        <span itemprop="name"><?= htmlspecialchars($item['TITLE']) ?></span>
                    </a>
                <?php else: ?>
                    <span class="breadcrumb__current" itemprop="item">
                        <span itemprop="name"><?= htmlspecialchars($item['TITLE']) ?></span>
                    </span>
                <?php endif; ?>
                <meta itemprop="position" content="<?= $index + 1 ?>">
            </li>
            
            <?php if (!$isLast): ?>
                <li class="breadcrumb__separator" aria-hidden="true">/</li>
            <?php endif; ?>
        <?php endforeach; ?>
    </ol>
</nav>

Три решения в этом шаблоне, которые стоят пояснения.

return при пустом $arResult — без него на страницах без цепочки в вёрстку попадёт пустой <nav> с отступами, и появится «необъяснимая дырка» над заголовком.

Последний элемент — не ссылка. Ссылка на страницу, на которой пользователь уже находится, бесполезна для него и вредна для внутренней перелинковки.

htmlspecialchars на TITLE. Заголовок приходит из названия элемента инфоблока — то есть из данных, которые вводит контент-менеджер. Кавычка в названии товара без экранирования ломает вёрстку, а в худшем случае даёт XSS через админку.

style.css

css
.breadcrumb {
    margin-bottom: 1.5rem;
    font-size: 0.875rem;
}

.breadcrumb__list {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.5rem;
    list-style: none;
    padding: 0;
    margin: 0;
}

.breadcrumb__item {
    display: inline-flex;
    align-items: center;
}

.breadcrumb__link {
    color: var(--muted);
    text-decoration: none;
    transition: color 0.2s;
}

.breadcrumb__link:hover {
    color: var(--accent);
}

.breadcrumb__current {
    color: var(--fg);
    font-weight: 500;
}

.breadcrumb__separator {
    color: var(--border);
    user-select: none;
}

/* Мобильная версия — скрываем промежуточные элементы */
@media (max-width: 640px) {
    .breadcrumb__item:not(:first-child):not(:last-child) {
        display: none;
    }
    
    .breadcrumb__separator:not(:first-of-type):not(:last-of-type) {
        display: none;
    }
}
⚠️ Важно

Скрытие промежуточных пунктов на мобильных через display: none — компромисс, о котором стоит знать. Элементы остаются в DOM и в микроразметке, поэтому поисковики цепочку видят целиком, но пользователь мобильной версии теряет контекст. Если уровней вложенности больше трёх, лучше сделать горизонтальную прокрутку цепочки, чем прятать её середину.

Добавление пунктов в цепочку

Из компонента (автоматически)

Большинство компонентов Битрикса автоматически добавляют пункты:

  • news.detail — название новости
  • catalog.element — название товара
  • catalog.section — название раздела

Вручную на странице

php
<?php
// В начале страницы
$APPLICATION->AddChainItem("Название пункта", "/url/страницы/");

// Несколько пунктов
$APPLICATION->AddChainItem("Каталог", "/catalog/");
$APPLICATION->AddChainItem("Смартфоны", "/catalog/smartphones/");
$APPLICATION->AddChainItem("iPhone 15 Pro");  // Без ссылки — текущая страница
?>

Через свойства страницы

В файле раздела .section.php:

php
<?php
$APPLICATION->SetPageProperty("nav_chain", [
    ["TITLE" => "Каталог", "LINK" => "/catalog/"],
    ["TITLE" => "Смартфоны", "LINK" => "/catalog/smartphones/"],
]);
?>

Микроразметка Schema.org

Шаблон выше уже включает разметку BreadcrumbList. Результат в HTML:

html
<ol itemscope itemtype="https://schema.org/BreadcrumbList">
    <li itemprop="itemListElement" itemscope itemtype="https://schema.org/ListItem">
        <a itemprop="item" href="/">
            <span itemprop="name">Главная</span>
        </a>
        <meta itemprop="position" content="1">
    </li>
    ...
</ol>

Проверка разметки: Google Rich Results Test

JSON-LD разметка (альтернатива)

Микроразметка атрибутами привязана к вёрстке: поменяли шаблон — потеряли разметку, и узнаете вы об этом из отчёта в Search Console через пару недель. JSON-LD от вёрстки не зависит, поэтому Google сам рекомендует именно его. Держать оба варианта одновременно не нужно — это дублирование одной сущности.

php
<?php
// result_modifier.php

$jsonLd = [
    '@context' => 'https://schema.org',
    '@type' => 'BreadcrumbList',
    'itemListElement' => [],
];

foreach ($arResult as $index => $item) {
    $jsonLd['itemListElement'][] = [
        '@type' => 'ListItem',
        'position' => $index + 1,
        'name' => $item['TITLE'],
        'item' => !empty($item['LINK']) 
            ? (strpos($item['LINK'], 'http') === 0 ? $item['LINK'] : 'https://' . $_SERVER['HTTP_HOST'] . $item['LINK'])
            : null,
    ];
}

$arResult['JSON_LD'] = json_encode($jsonLd, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
?>
php
<!-- template.php -->
<script type="application/ld+json">
<?= $arResult['JSON_LD'] ?>
</script>

Хлебные крошки внутри компонента

Для отображения цепочки внутри компонента (не в header.php):

php
<?php
// В шаблоне компонента
$APPLICATION->IncludeComponent(
    "bitrix:breadcrumb",
    "inline",
    [
        "START_FROM" => "1", // Пропустить "Главная"
        "PATH" => $arResult['SECTION']['SECTION_PAGE_URL'],
    ]
);
?>
⚠️ Важно

В JSON-LD нужны абсолютные URL. В примере выше хост берётся из $_SERVER['HTTP_HOST'] — это заголовок запроса, которым управляет клиент. На сайте без строгой проверки Host в конфиге веб-сервера туда попадёт что угодно, и в разметке окажутся ссылки на чужой домен. Берите хост из настроек сайта Битрикса (SITE_SERVER_NAME или поле сайта), а не из запроса.

Итоги

Что я проверяю на приёмке шаблона крошек:

  1. На главной цепочки нет — ни в вёрстке, ни в разметке.
  2. Последний пункт не является ссылкой и совпадает с H1 страницы по смыслу (не обязательно дословно — в крошках уместнее короткое название).
  3. Разметка одна, микроданные или JSON-LD, и она проходит Rich Results Test.
  4. Абсолютные URL в JSON-LD собираются из настроек сайта, а не из заголовка Host.
  5. Названия экранируются — данные приходят от контент-менеджера.
  6. Глубина цепочки — до 4–5 уровней. Дело не в мифическом «SEO-вреде», а в том, что более длинная цепочка не помещается на экран и перестаёт выполнять свою единственную задачу: показывать, где пользователь находится.
🚀

Хотите такое же решение?

Настрою окружение под ваш проект, учту специфику инфраструктуры и обучу команду.

Обсудить проект →
Бесплатная консультация · Ответ в течение дня

Комментарии

Система комментариев скоро будет подключена. А пока вы можете написать мне в Telegram или на email.