⚡IntermediateStructured Data and SEO

Breadcrumb Navigation

Build accessible, SEO-friendly breadcrumb trails with nav, aria-label, and JSON-LD.

Overview

Breadcrumbs show users their location within a site hierarchy and provide quick navigation to parent pages. Example: Home > Courses > HTML > Beginner. A well-implemented breadcrumb has three layers: 1. Semantic HTML: <nav aria-label="Breadcrumb"> with an ordered list 2. Accessibility: aria-current="page" on the current page item 3. Structured data: BreadcrumbList JSON-LD for Google rich results The current page link (last item) is typically not a link, or is an <a> with aria-current="page" to signal it's the current location.

Key Points

  • •Wrap breadcrumbs in <nav aria-label="Breadcrumb"> for accessibility
  • •Use <ol> (ordered list) breadcrumbs imply sequence/hierarchy
  • •aria-current="page" on the last item signals the current page to screen readers
  • •The last breadcrumb item is often plain text (not a link) since it's the current page
  • •Separate items visually with CSS content (not HTML entities) to avoid screen reader noise
  • •Pair HTML breadcrumbs with BreadcrumbList JSON-LD for Google breadcrumb rich results

Examples

Accessible semantic breadcrumb

<nav aria-label="Breadcrumb">
  <ol>
    <li>
      <a href="/">Home</a>
    </li>
    <li>
      <a href="/courses">Courses</a>
    </li>
    <li>
      <a href="/courses/html">HTML</a>
    </li>
    <li>
      <!-- Current page: not a link, marked with aria-current -->
      <span aria-current="page">Beginner</span>
    </li>
  </ol>
</nav>

aria-current="page" tells screen readers this is the current page.

CSS-only separators (screen reader friendly)

<style>
  .breadcrumb { list-style: none; display: flex; gap: 0; }
  .breadcrumb li + li::before {
    content: "/";
    margin: 0 8px;
    color: #6b7280;
    aria-hidden: true;  /* CSS content is ignored by screen readers */
  }
</style>

<nav aria-label="Breadcrumb">
  <ol class="breadcrumb">
    <li><a href="/">Home</a></li>
    <li><a href="/docs">Docs</a></li>
    <li><span aria-current="page">HTML Guide</span></li>
  </ol>
</nav>

CSS-generated content via ::before is not read by most screen readers cleaner than HTML separators.

JSON-LD BreadcrumbList for rich results

<script type="application/ld+json">
{
  "@context": "https://schema.org",
  "@type": "BreadcrumbList",
  "itemListElement": [
    {
      "@type": "ListItem",
      "position": 1,
      "name": "Home",
      "item": "https://example.com/"
    },
    {
      "@type": "ListItem",
      "position": 2,
      "name": "Courses",
      "item": "https://example.com/courses"
    },
    {
      "@type": "ListItem",
      "position": 3,
      "name": "HTML",
      "item": "https://example.com/courses/html"
    },
    {
      "@type": "ListItem",
      "position": 4,
      "name": "Beginner"
    }
  ]
}
</script>

The last item has no "item" URL it's the current page.

Common Mistakes

  • Using <ul> instead of <ol> breadcrumbs are ordered by hierarchy, making <ol> semantically correct
  • Adding / separators as visible text or HTML entities they get read by screen readers
  • Not marking the current page with aria-current="page"

Note

Implement both the HTML breadcrumb AND the JSON-LD BreadcrumbList. The HTML breadcrumb is for users; the JSON-LD is for search engines to show the path in search results (URL replaced by "Home › Courses › HTML").

Exercises

Write HTML to solve each exercise. Use Preview to see it render in a live iframe, then mark as done.

Loading editor…

Completed: 0 / 5 exercises

Knowledge Check

Question 1 of 4

Why should breadcrumbs use <ol> instead of <ul>?