Skip to main content

Breadcrumbs

Overview

Breadcrumbs is a server-rendered navigation component that automatically builds a breadcrumb trail from the active WordPress query. Unlike interactive components (Accordion, Tabs, etc.), Breadcrumbs has no client-side runtime — the trail is resolved entirely in PHP during block rendering and injected into the page as final HTML.

The component automatically handles pages with parent/ancestor hierarchies, single posts with category ancestry, custom post type archives, term archives, date archives, author archives, search results, and 404 pages. It also outputs BreadcrumbList JSON-LD structured data for SEO when enabled.

Breadcrumbs is a single-component family — there are no sub-components. It is placed into patterns or templates and the server-side trail resolver does the rest.

Authoring Structure

Breadcrumbs (OmeBreadcrumbs)
├── Home slot (optional custom home content)
└── Separator slot (optional custom separator content)

Placement Rules

SlotPurpose
homeCustom content inside the home link. When empty, the homeLabel text is used.
separatorCustom separator between items. When empty, the separator text is used.

How It Works

Breadcrumbs uses a two-phase rendering pipeline:

  1. Editor / Preview phase — The component renders a static preview with placeholder items ("Home", "Blog", "Current page") so the editor shows a representative breadcrumb trail.
  2. Frontend phase — A block interceptor (BreadcrumbsBlockInterceptor) replaces the placeholder with a real breadcrumb trail resolved from the current WordPress query context via BreadcrumbTrailResolver.

This means the breadcrumb trail is always accurate for the current page — no manual item configuration is needed.

Supported WordPress Contexts

ContextTrail
Front pageHidden by default (enable with showOnFrontPage).
Posts indexHome → Blog (or custom Posts Page).
Single postHome → Blog → Category → Post.
Page (with ancestors)Home → Parent → … → Page.
Custom post typeHome → Archive → Term (if hierarchical) → Post.
Post type archiveHome → Archive.
Term archiveHome → … → Term (with ancestor terms for hierarchical taxonomies).
Date archiveHome → Year → Month → Day (drills down as deep as the URL).
Author archiveHome → Author name.
Search resultsHome → Search.
404Home → Not Found.

Quick Start

Basic breadcrumbs
<OmeBreadcrumbs
content='{{"homeLabel":"Home","separator":"/","ariaLabel":"Breadcrumb"}}'
settings='{{"showHome":true,"showCurrent":true,"linkCurrent":false,"showOnFrontPage":false,"enableSchema":true}}'
/>
Breadcrumbs with custom separator slot
<OmeBreadcrumbs
content='{{"homeLabel":"Home","separator":"/","ariaLabel":"Breadcrumb"}}'
settings='{{"showHome":true,"showCurrent":true}}'
>
{#slot separator}
<span class="my-separator" aria-hidden="true"></span>
{/slot}
</OmeBreadcrumbs>
Breadcrumbs with custom home icon
<OmeBreadcrumbs
content='{{"homeLabel":"Home","separator":"/","ariaLabel":"Breadcrumb"}}'
settings='{{"showHome":true,"showCurrent":true}}'
>
{#slot home}
<svg class="home-icon" aria-hidden="true" width="16" height="16"><!-- icon SVG --></svg>
{/slot}
</OmeBreadcrumbs>

Props

Content Props

PropTypeDefaultDescription
homeLabelstringHome

Text used for the home breadcrumb. Shown when the home slot is empty.

separatorstring/

Text shown between breadcrumb items. Shown when the separator slot is empty.

ariaLabelstringBreadcrumb

Accessible label for the <nav> landmark. Screen readers announce this to identify the navigation region.

Settings Props

PropTypeDefaultDescription
showHomebooleantrue

Includes the home breadcrumb as the first item in the trail.

showCurrentbooleantrue

Includes the current page as the last item in the trail. When false, the trail ends at the parent item.

linkCurrentbooleanfalse

Renders the current page breadcrumb as a link (<a>) instead of a plain <span>. The current item always has aria-current="page" regardless of this setting.

showOnFrontPagebooleanfalse

Keeps breadcrumbs visible on the front page. When false (default), the component outputs nothing on the front page.

enableSchemabooleantrue

Outputs a BreadcrumbList JSON-LD script tag after the navigation markup. Schema is only rendered when there are at least two items with URLs. Disable this if your theme or an SEO plugin already provides breadcrumb schema.

Styling Props

PropTypeDefaultDescription
rootClassclassome-breadcrumbs-root-default

CSS class applied to the root <nav> element.

listClassclassome-breadcrumbs-list-default

CSS class applied to the <ol> list element.

itemClassclassome-breadcrumbs-item-default

CSS class applied to each <li> item element.

linkClassclassome-breadcrumbs-link-default

CSS class applied to each <a> link element.

currentClassclassome-breadcrumbs-current-default

CSS class applied to the current page item (whether rendered as a link or span).

separatorClassclassome-breadcrumbs-separator-default

CSS class applied to each separator <span> element.


Default CSS

The default styles provide a horizontal flex layout with ACSS-aware custom properties:

/* Root: inherits text color and uses small text size */
.ome-breadcrumbs-root-default {
color: var(--text-dark, currentColor);
font-size: var(--text-s, 0.875rem);
}

/* List: horizontal flexbox with wrapping */
.ome-breadcrumbs-list-default {
display: flex;
flex-wrap: wrap;
align-items: center;
gap: var(--space-xs, 0.75rem);
margin: 0;
padding: 0;
}

/* Items: inline flex, no list style */
.ome-breadcrumbs-item-default {
display: inline-flex;
align-items: center;
gap: var(--space-xs, 0.75rem);
list-style: none;
}

The fixed base styles enforce box-sizing: border-box, hide [hidden] elements, and provide :focus-visible outline styling on links — matching the same foundation used across all Etch components.


Accessibility

The rendered markup uses semantic HTML:

  • The root element is a <nav> with aria-label (defaults to "Breadcrumb").
  • The list uses an ordered list <ol> for correct semantics.
  • The current page item has aria-current="page".
  • Separators are marked aria-hidden="true" to avoid screen reader noise.
  • :focus-visible outlines are provided by the fixed base styles.

Common Mistakes

Expecting client-side runtime behavior

Breadcrumbs is entirely server-rendered. There is no JavaScript runtime for this component — the trail is resolved in PHP during render_block. You cannot dynamically update breadcrumbs with client-side JavaScript.

Setting showOnFrontPage to false and expecting output on the homepage

By default showOnFrontPage is false, which means the component outputs nothing on the front page. If your design calls for breadcrumbs on the homepage, set showOnFrontPage to true and showHome to true.

Enabling schema when an SEO plugin already outputs BreadcrumbList

If you use Yoast SEO, Rank Math, or another plugin that generates BreadcrumbList JSON-LD, set enableSchema to false to avoid duplicate schema output.

Expecting the editor preview to match the frontend trail

The editor renders static placeholder items ("Home", "Blog", "Current page") so you can preview the visual design. The actual breadcrumb trail is only generated on the frontend from the real WordPress query context.


FAQs

Can I customize which categories appear for single posts?

The trail resolver picks the first assigned term (lowest term_id) from the post's categories. To control which category appears, assign only one category to the post, or use a plugin that filters get_the_terms.

Does this work with custom post types?

Yes. For custom post types with has_archive, the resolver includes the post type archive link. If the post type has hierarchical taxonomies, the first assigned term in the first public hierarchical taxonomy is included in the trail.

Can I use a custom icon or SVG for the separator?

Yes. Use the separator slot to provide custom markup instead of the plain text separator:

<OmeBreadcrumbs>
{#slot separator}
<span aria-hidden="true">
<svg><!-- your icon --></svg>
</span>
{/slot}
</OmeBreadcrumbs>
What happens on pages with no ancestors?

For a top-level page, the trail is simply: Home → Page Title. For nested pages, each ancestor is included in order: Home → Parent → Grandparent → Page Title.

Why is the schema not appearing?

Schema output requires at least two items with URLs in the trail. If showHome is false and only the current page remains, or if the trail has fewer than two linkable items, the JSON-LD script tag is omitted. Also check that enableSchema is true.