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
};