Static breadcrumbs

The simplest rendering: an {#each} loop, no transitions. Toggle "Animate breadcrumbs" in the sidebar to compare.

Basic example

Link every segment except the last; mark that one as the current page.

<script lang="ts">
  import { getCrumbs } from 'svelte-crumbs';

  const crumbs = $derived(await getCrumbs());
</script>

<nav aria-label="Breadcrumbs" class="flex items-center gap-2 text-sm">
  {#each crumbs as crumb, i (crumb.url)}
    {#if i > 0}
      <span aria-hidden="true">/</span>
    {/if}
    {#if i < crumbs.length - 1 || crumbs.length === 1}
      <a href={crumb.url}>{crumb.label}</a>
    {:else}
      <span aria-current="page">{crumb.label}</span>
    {/if}
  {/each}
</nav>

With icons

A crumb can carry an icon — a Svelte component returned from the resolver. Render it beside the label.

<nav aria-label="Breadcrumbs" class="flex items-center gap-2 text-sm">
  {#each crumbs as crumb, i (crumb.url)}
    {#if i > 0}
      <span aria-hidden="true">/</span>
    {/if}
    <span class="inline-flex items-center gap-1">
      {#if crumb.icon}
        {@const Icon = crumb.icon}
        <Icon />
      {/if}
      {#if i < crumbs.length - 1 || crumbs.length === 1}
        <a href={crumb.url}>{crumb.label}</a>
      {:else}
        <span aria-current="page">{crumb.label}</span>
      {/if}
    </span>
  {/each}
</nav>

Custom separators

You own the markup: arrows, chevrons, dots, custom SVGs.

{#each crumbs as crumb, i (crumb.url)}
  {#if i > 0}
    <svg class="w-4 h-4" viewBox="0 0 24 24" fill="none"
      stroke="currentColor" stroke-width="2">
      <path d="M9 18l6-6-6-6" />
    </svg>
  {/if}
  <a href={crumb.url}>{crumb.label}</a>
{/each}

The crumbs array

Each entry has this shape:

type Breadcrumb = {
  label: string;       // resolved display text
  url: string;         // the URL path for this segment
  icon?: Component;    // optional Svelte component
};