Хлебные крошки (breadcrumbs)
Навигационная цепочка «Главная / Каталог / Товар» с семантическим HTML, ARIA и микроразметкой Schema.org.
Задача
Нужен компонент хлебных крошек для навигации по вложенной структуре страниц. Должен быть доступным, SEO-friendly и генерироваться динамически из массива данных.
Решение
<!-- Статический вариант -->
<nav class="breadcrumbs" aria-label="Навигация по сайту">
<ol class="breadcrumbs__list" itemscope itemtype="https://schema.org/BreadcrumbList">
<li class="breadcrumbs__item" itemprop="itemListElement" itemscope itemtype="https://schema.org/ListItem">
<a class="breadcrumbs__link" href="/" itemprop="item">
<span itemprop="name">Главная</span>
</a>
<meta itemprop="position" content="1" />
</li>
<li class="breadcrumbs__item" itemprop="itemListElement" itemscope itemtype="https://schema.org/ListItem">
<a class="breadcrumbs__link" href="/catalog/" itemprop="item">
<span itemprop="name">Каталог</span>
</a>
<meta itemprop="position" content="2" />
</li>
<li class="breadcrumbs__item breadcrumbs__item--current"
itemprop="itemListElement" itemscope itemtype="https://schema.org/ListItem"
aria-current="page">
<span itemprop="name">Ноутбук Pro 15</span>
<meta itemprop="position" content="3" />
</li>
</ol>
</nav>
.breadcrumbs__list {
display: flex;
align-items: center;
flex-wrap: wrap;
gap: 4px;
list-style: none;
padding: 0;
margin: 0;
font-size: 0.875rem;
}
.breadcrumbs__link {
color: #3b82f6;
text-decoration: none;
}
.breadcrumbs__link:hover { text-decoration: underline; }
/* Разделитель через CSS content */
.breadcrumbs__item:not(:last-child)::after {
content: '/';
margin-left: 4px;
color: #94a3b8;
}
.breadcrumbs__item--current {
color: #64748b;
}
JavaScript — динамическая генерация из массива:
function renderBreadcrumbs(container, crumbs) {
const nav = document.createElement('nav');
nav.setAttribute('aria-label', 'Навигация по сайту');
const ol = document.createElement('ol');
ol.className = 'breadcrumbs__list';
crumbs.forEach((crumb, index) => {
const li = document.createElement('li');
li.className = 'breadcrumbs__item';
const isLast = index === crumbs.length - 1;
if (isLast) {
li.classList.add('breadcrumbs__item--current');
li.setAttribute('aria-current', 'page');
li.textContent = crumb.label;
} else {
const a = document.createElement('a');
a.className = 'breadcrumbs__link';
a.href = crumb.href;
a.textContent = crumb.label;
li.appendChild(a);
}
ol.appendChild(li);
});
nav.appendChild(ol);
container.innerHTML = '';
container.appendChild(nav);
}
// Использование
renderBreadcrumbs(document.getElementById('breadcrumbs'), [
{ label: 'Главная', href: '/' },
{ label: 'Каталог', href: '/catalog/' },
{ label: 'Ноутбук Pro 15' },
]);
Ключевые моменты
<nav>+aria-label— screen reader объявит «Навигация по сайту».<ol>(ordered list) — хлебные крошки имеют порядок, не<ul>.aria-current="page"на последнем элементе — означает «текущая страница».- Schema.org
BreadcrumbList— Google показывает крошки прямо в результатах поиска (rich snippets).
Варианты
- SVG-разделитель вместо
/:content: url("chevron.svg")или>черезcontent: '›'. - В React/Next.js — генерируй из
useRouter.pathnameразбивкой на сегменты пути.