Build Breadcrumb Navigation From Hugo's Page Hierarchy

Breadcrumbs are useful when a page sits inside a hierarchy that visitors may want to climb back through:

Home → Blog → CSS → Article

Hugo already knows those relationships. The template can generate the trail from page ancestors, which is safer than typing it into every article or trying to reconstruct it from pieces of the URL.

Start with semantic navigation

A breadcrumb is an ordered path, so the plain HTML should look roughly like this:

<nav aria-label="Breadcrumb">
  <ol>
    <li><a href="/">Home</a></li>
    <li><a href="/blogs/">Blog</a></li>
    <li>Current article</li>
  </ol>
</nav>

The current page does not need to link to itself. It should, however, be identifiable as the current item.

Let .Ancestors build the middle

This partial adds Home, walks through the current page’s ancestors in display order, and finishes with the current title:

<nav aria-label="Breadcrumb">
  <ol>
    <li>
      <a href="{{ site.Home.RelPermalink }}">
        Home
      </a>
    </li>

    {{ range .Ancestors.Reverse }}
      {{ if not .IsHome }}
        <li>
          <a href="{{ .RelPermalink }}">
            {{ .LinkTitle }}
          </a>
        </li>
      {{ end }}
    {{ end }}

    <li aria-current="page">
      {{ .LinkTitle }}
    </li>
  </ol>
</nav>

The exact filtering depends on the site structure. A section used only for organization may not deserve a place in the visible trail.

Put the code in a partial:

layouts/
└── partials/
    └── breadcrumbs.html

Then call it from the relevant page template:

{{ partial "breadcrumbs.html" . }}

Keep the trail readable

Flexbox is enough for a trail that wraps on small screens:

.breadcrumbs ol {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;

  list-style: none;
  padding: 0;
  margin: 0;
}

Decorative separators can stay in CSS:

.breadcrumbs li + li::before {
  content: "→";
  margin-right: 0.5rem;
}

Long article titles can overwhelm the trail. Hugo’s .LinkTitle lets a page supply a shorter navigation label while keeping its full title elsewhere.

Do not manufacture a hierarchy

Breadcrumbs are secondary navigation, not a replacement for the main menu. They help most on documentation, shops, large blogs, and sites with nested sections. A three-page portfolio probably gains more clutter than context.

Visual breadcrumbs also do not automatically create breadcrumb structured data. Add that separately if the site needs it, and keep the visible HTML useful without it.

I would generate breadcrumbs from Hugo’s page model only where that model reflects a real path a visitor understands. When it does, moving content to another section updates the navigation automatically—the kind of repetitive work a static site generator should quietly remove.

Comments