Хлебные крошки — это путь от главной страницы до той, на которой человек сейчас находится. Название пришло из сказки о Гензеле и Гретель: дети бросали за собой крошки, чтобы найти дорогу назад. На сайте крошки работают так же — показывают, где ты, и дают выйти на уровень выше.

Зачем они нужны

Пока на сайте пять страниц, крошки кажутся мелочью. Дальше они начинают делать три полезные вещи.

  • Показывают положение. Человек видит не просто «страница про чанки», а «Этапы → Выбор инструментов → Чанки»: сразу понятно, что это часть большого раздела и что рядом есть другие такие же страницы.
  • Дают выход на уровень выше. На внутреннюю страницу часто попадают прямо из поиска, минуя главную. Без крошек единственный способ осмотреться — искать нужный пункт в меню; с крошками уровень выше в одном щелчке.
  • Попадают в поисковую выдачу. Если добавить микроразметку, поисковик показывает под заголовком не голый адрес eazy-logic.ru/manualy/hlebnye-kroshki/, а понятный путь «Easy Logic › Мануалы › Хлебные крошки».

Где крошек быть не должно

На главной странице: путь из одного пункта «Главная» не сообщает ничего. И на сайте без вложенности — если все страницы лежат в корне, показывать нечего.

Разметка: это список, а не строка текста

Самая частая ошибка — сверстать крошки обычным абзацем, поставив между ссылками слэши или стрелки. Выглядит похоже, а по смыслу это другое: путь — упорядоченный список, порядок пунктов в нём важен. Поэтому берём <ol> и оборачиваем его в <nav>: это навигация, и программа чтения экрана должна уметь назвать её отдельно.

Крошки этой страницы
<nav class="breadcrumbs" aria-label="Вы находитесь здесь">
  <ol class="breadcrumbs__list">
    <li class="breadcrumbs__item">
      <a class="breadcrumbs__link" href="/">Главная</a>
    </li>
    <li class="breadcrumbs__item">
      <a class="breadcrumbs__link" href="/manualy/">Мануалы</a>
    </li>
    <li class="breadcrumbs__item">
      <span class="breadcrumbs__current" aria-current="page">Хлебные крошки</span>
    </li>
  </ol>
</nav>

Три вещи в этой разметке стоят не для красоты.

Что за что отвечает в разметке крошек
Что Зачем
<nav> Помечает область как навигацию. Человек с программой чтения экрана переходит к ней одной командой, не слушая страницу с начала.
aria-label Название этой навигации. На странице есть ещё меню и оглавление — без названий все три объявлялись бы одинаково: «навигация».
aria-current="page" Отмечает текущую страницу. Ссылкой последний пункт не делаем: вести туда, где уже стоишь, незачем, да и лишняя остановка при обходе по Tab не нужна.

Разделитель в разметку не пишем

Слэш или стрелку между пунктами хочется поставить прямо в HTML — так делают чаще всего. Но это текст, и программа чтения экрана его прочитает: «Главная, слэш, Мануалы, слэш, Хлебные крошки». Разделитель — оформление, его место в CSS.

Стили: уголок вместо символа

Разделитель рисуем псевдоэлементом ::before у каждого пункта, кроме первого. Сам уголок — это две границы квадратика 5×5, повёрнутые на 45 градусов. Так получается ровная «птичка» без картинки и без иконки в спрайте.

assets/css/components.css
.breadcrumbs__list {
  display: flex;
  flex-wrap: wrap;        /* на узком экране путь переносится на вторую строку */
  align-items: center;
  gap: 8px;
  font-size: 0.8125rem;
}

.breadcrumbs__item {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  color: #5A6873;
}

/* Разделитель: две границы квадратика, повёрнутые на 45°.
   В разметке его нет — читать «слэш» диктору незачем. */
.breadcrumbs__item + .breadcrumbs__item::before {
  content: "";
  width: 5px;
  height: 5px;
  border-top: 1.5px solid #8A97A1;
  border-right: 1.5px solid #8A97A1;
  transform: rotate(45deg);
}

.breadcrumbs__link {
  color: #5A6873;
  text-decoration: none;
}

.breadcrumbs__link:hover {
  color: #1565D8;
  text-decoration: underline;
}

/* Текущая страница видна и без ссылки: цветом и насыщенностью */
.breadcrumbs__current {
  color: #2F3A42;
  font-weight: 500;
}

Два места, где крошки ломаются чаще всего, закрыты здесь заранее. flex-wrap: wrap разрешает пути перенестись на вторую строку: без него длинный путь на телефоне растягивает страницу вбок. А мелкий кегль взят намеренно — крошки служебная строка, спорить с заголовком ей не положено.

Микроразметка: путь для поисковика

Глазами путь виден, а поисковый робот видит набор ссылок и не знает, что это именно путь. Чтобы объяснить, рядом кладут те же данные в формате для машины. Формат, которым пользуется наш сайт, называется Данные о странице, записанные обычным JSON внутри тега script. На вид страницы не влияют: человек их не видит, читает только поисковый робот. .

Перед закрывающим </body>
<script type="application/ld+json">
{
  "@context": "https://schema.org",
  "@type": "BreadcrumbList",
  "itemListElement": [
    { "@type": "ListItem", "position": 1, "name": "Главная",
      "item": "https://eazy-logic.ru/" },
    { "@type": "ListItem", "position": 2, "name": "Мануалы",
      "item": "https://eazy-logic.ru/manualy/" },
    { "@type": "ListItem", "position": 3, "name": "Хлебные крошки",
      "item": "https://eazy-logic.ru/manualy/hlebnye-kroshki/" }
  ]
}
</script>

Четыре правила, без которых разметку не примут.

  1. position начинается с единицы и идёт без пропусков: 1, 2, 3.
  2. item — полный адрес со https://, а не /manualy/. Робот читает страницу отдельно от сайта и достраивать короткий адрес не обязан.
  3. name совпадает с тем, что человек видит на экране. Разные названия в разметке и на странице поисковик считает попыткой его обмануть и разметку просто не учитывает.
  4. Порядок пунктов — от главной к текущей странице, тот же, что в видимых крошках.

Проверить результат можно сразу и бесплатно: Страница, куда вставляют адрес сайта или кусок кода, а она показывает, что робот из этой разметки прочитал и где ошибка. Такие есть у Яндекса — в Вебмастере, — и у Google. покажет дерево из трёх пунктов, ровно то, что мы написали. Подробнее про сам формат — в статье «Микроразметка».

Порядок действий

Всё вместе — четыре шага. Картинку можно увеличить щелчком: видно, что должно получиться на каждом.

Те же крошки в Evolution CMS

Пока страница одна, путь можно написать руками. На полусотне страницах так уже не выйдет: у каждой путь свой. И чанк здесь не поможет — чанк подставляет один и тот же кусок текста всюду, а крошки зависят от того, где страница лежит в дереве. Значит, работа для сниппета: он смотрит на родителей текущего ресурса и собирает путь сам.

Шаблон внутренней страницы
<!-- было в статической вёрстке -->
<nav class="breadcrumbs" aria-label="Вы находитесь здесь">
  <ol class="breadcrumbs__list">
    ... двенадцать строк, свои на каждой странице ...
  </ol>
</nav>

<!-- стало в шаблоне MODX -->
[[Breadcrumbs]]

Сниппет Breadcrumbs в Evolution есть из коробки. У него есть параметры: показывать ли главную, показывать ли текущую страницу, чем разделять пункты. Имена параметров у разных версий немного отличаются, поэтому точный список смотрите в описании сниппета в админке — а проверим мы это на этапе натягивания вёрстки.

Остаётся вторая половина работы. Сниппет отдаёт видимые крошки, а микроразметку — нет: её тоже нужно собрать из пути, и названия в ней обязаны совпасть с видимыми. С этим я пошёл к нейросети.

Мой запрос

Сайт на Evolution CMS 3. В шаблоне внутренней страницы видимые хлебные крошки выводит сниппет Breadcrumbs. Мне нужна ещё микроразметка BreadcrumbList в формате JSON-LD, причём названия и порядок пунктов должны совпадать с видимыми крошками.

Объясни план: откуда взять путь от главной до текущего ресурса, где разместить вывод в шаблоне и как получить полные адреса со схемой и доменом, а не относительные.

Отдельно предупреди про подводные камни: кэш, страницы вне дерева, главная страница — на ней крошек быть не должно.

Ответ нейросети

Откуда брать путь. У каждого ресурса есть поле parent — идентификатор родителя. Поднимаясь по нему от текущей страницы до корня, вы получите список предков; разверните его в обратном порядке, и это будет путь от главной. Ровно так же работает и сам сниппет Breadcrumbs — второй раз изобретать логику не нужно, достаточно взять тот же список.

Полные адреса. Адрес ресурса по его номеру даёт функция построения ссылки, а домен со схемой лежит в системной настройке site_url. Складывайте их — получится абсолютный адрес, который требует schema.org. Относительный путь в микроразметке робот не примет.

Где разместить. В шаблоне, перед закрывающим тегом </body>, вместе с остальной микроразметкой. В <head> тоже можно, но там и без этого много.

Подводные камни. Кэш вам не помешает: в Evolution он свой для каждой страницы, а путь у страницы не меняется. Главную страницу проверьте отдельно и выводите на ней пустую строку — путь из одного пункта поисковику не нужен. И следите за совпадением названий: если в видимых крошках короткое название, а в разметке длинный заголовок, разметка будет считаться недостоверной.

Совет про короткое название пригодился сразу

У этой страницы заголовок в поисковой выдаче — «Хлебные крошки: вёрстка и микроразметка», а в крошках стоит просто «Хлебные крошки». Полное название заняло бы на телефоне три строки. В CMS для такого держат отдельное поле «название в меню».

Частые ошибки

Пять поломок, которые встречаются чаще всего. Первые две — как раз те, с которых начинал я сам.

Как ломают крошки и что делать вместо этого
Ошибка Чем плохо Как правильно
Крошки абзацем со слэшами Диктор читает слэши как слова, робот не видит структуры Список ol, разделитель в CSS
Последний пункт — ссылка на себя Переход в никуда и лишняя остановка при обходе по Tab span с aria-current="page"
В крошках история переходов У одной страницы путь каждый раз разный, доверять ему нельзя Путь строится по вложенности страниц в сайте
Разметка не совпадает с видимым путём Поисковик считает это обманом и разметку не учитывает Одни и те же названия и тот же порядок
Длинное название в крошках На телефоне путь занимает три строки и давит на заголовок Короткое название для крошек и меню

Что должно получиться

  • Путь стоит на всех страницах, кроме главной, и ведёт от неё до текущей
  • Последний пункт — не ссылка, у него aria-current="page"
  • Разделителя нет в разметке: он нарисован в CSS
  • На 320 пикселях путь переносится на вторую строку и не растягивает страницу
  • Валидатор видит BreadcrumbList с теми же названиями, что на экране