useBreadcrumbItems()
Usage
Use the auto-imported useBreadcrumbItems
composable to generate an automatic breadcrumb list that helps users to navigate between pages.
- Integrates with Nuxt Schema.org to generate BreadcrumbList structured data.
- Integrates with Nuxt I18n to generate localized breadcrumbs.
Demo
This demo integrates directly with the Nuxt UI Breadcrumb component.
<script lang="ts" setup>
const items = useBreadcrumbItems() // uses the current route
</script>
<template>
<UBreadcrumb :items="items"/>
</template>
<script lang="ts" setup>
const items = useBreadcrumbItems() // uses the current route
</script>
<template>
<nav aria-label="Breadcrumbs">
<ul>
<li v-for="(item, key) in items" :key="key">
<NuxtLink v-bind="item">
{{ item.label }}
</NuxtLink>
</li>
</ul>
</nav>
</template>
Modifying Breadcrumbs
Because the breadcrumb is generated automatically, you may need to modify the final output.
It's important to do this within the defineBreadcrumbItems
function, as it will ensure that the Schema.org is generated correctly.
Route Meta
If you need to modify the breadcrumb for a specific static route, you can use the breadcrumb
property of the route meta.
<script lang="ts" setup>
definePageMeta({
breadcrumb: {
icon: 'i-heroicons-home',
ariaLabel: 'Home'
},
})
</script>
Overrides
When you need more control over the final output, you can use the overrides
prop. This allows
you to override any part of the breadcrumb.
The property takes an array of either: BreadcrumbItem
, false
or undefined
, the array
of overrides is applied in the order they are provided.
When providing undefined
, nothing will be overridden. When providing false
, the breadcrumb
will be removed.
For example, if you have the path /blog/my-post
and you want to override the my-post
segment, we need
to target the third item in the array.
// path: /blog/my-post will generate ['Home', 'Blog', 'My Post']
useBreadcrumbItems({
overrides: [
undefined, // Home
undefined, // Blog
{
label: 'My Awesome Post',
to: '/blog/my-post',
icon: 'i-heroicons-home'
}
]
})
append
and prepend
If you need to add items to the end or beginning of the breadcrumb, you can use the append
and prepend
props.
import { useBreadcrumbItems } from '#imports'
useBreadcrumbItems({
append: [
{
label: 'Final Link'
}
]
})
I18n Integration
If you're using the @nuxtjs/i18n module, you can use the key breadcrumbs.items.${routeName}
.
Where routeName
is the generated name of the Vue Router route.
export default {
breadcrumb: {
items: {
index: {
icon: 'i-heroicons-home',
ariaLabel: 'Home'
}
}
}
}
{
"breadcrumb": {
"items": {
"index": {
"icon": "i-heroicons-home",
"ariaLabel": "Home"
}
}
}
}
Hierarchical Breadcrumbs
It's common to want to have a breadcrumb in your top-level layout and then have this be completely dynamic for each page.
While this will work, it gets more complicated once you need to start overriding the breadcrumb list for data that's only available from a fetch.
Consider a blog example where we want to show something like:
- Blog (
/blog
) -> Dynamic Category (/blog/dynamic-category
) -> Post title (/blog/dynamic-category/post-title
)
You would be tempted to insert the breadcrumb in the blog layout. However, this has issues.
<script lang="ts" setup>
import { useBreadcrumbItems } from '#imports'
const items = useBreadcrumbItems({
rootNode: '/blog',
overrides: [
{ label: 'My Cool Blog', }, // Home
// ❌ We're missing data to render the post title and category
]
})
</script>
<template>
<div>
<Breadcrumb :items="useBreadcrumbItems()" />
</div>
</template>
Instead, we need to render the breadcrumb list as late as possible in the render tree. This means we need to insert the breadcrumb in the page component.
However, this means we may need to do prop drilling to get the data to the breadcrumb. Instead, we can use the shared
breadcrumb context that's based on the id
.
<script lang="ts" setup>
// setup root breadcrumb config
useBreadcrumbItems({
overrides: [
{ label: 'My Cool Site', },
]
})
</script>
<script lang="ts" setup>
// example path /blog/<category>/<post>
const category = await useFetch<{ slug: string }>('/api/category', { params: { category: useRoute().params.category } })
// setup breadcrumb root config
useBreadcrumbItems({
overrides: [
undefined,
{ label: 'Category', to: `/blog/${category.value.slug}` },
]
})
</script>
<template>
<div>
<!-- ❌ don't render breadcrumbs here -->
</div>
</template>
<script lang="ts" setup>
definePageMeta({
layout: 'blog',
})
// example
const post = await useFetch('/api/post', { params: { post: useRoute().params.post } })
const items = useBreadcrumbItems({
overrides: [
undefined, // avoid overriding the root
undefined,
{ label: 'Post Title', to: `/blog/${useRoute().params.category}/${post.value.slug}` }
]
})
</script>
<template>
<div>
<!-- ✅ render breadcrumbs here -->
</div>
</template>
This may change your design a bit, but it's the only way to reliable handle this without a hydration issue.
Props
path
- Type:
string
- Default:
getRoute().path
The path to generate the breadcrumb for.
schemaOrg
- Type:
boolean
- Default:
false
Whether to generate BreadcrumbList structured data.
ariaLabel
- Type:
string
- Default:
'Breadcrumbs'
The Aria Label for the breadcrumbs.
hideRoot
- Type:
MaybeRefOrGetter<boolean>
- Default:
false
Whether the root breadcrumb should be shown.
hideCurrent
- Type:
MaybeRefOrGetter<boolean>
- Default:
false
Whether the current breadcrumb should be shown. This is usually the last item in the breadcrumb, but not always.
overrides
- Type:
(BreadcrumbItem | false | undefined)[]
- Default:
[]
An array of items to override the generated breadcrumbs with.
append
- Type:
BreadcrumbItem[]
- Default:
[]
An array of items to append to the generated breadcrumbs.
prepend
- Type:
BreadcrumbItem[]
- Default:
[]
An array of items to prepend to the generated breadcrumbs.
rootNode
- Type:
string
- Default:
undefined
The root node to use for the breadcrumb. This is useful for when you want to generate a breadcrumb for a specific route.
The default will either use /
or the i18n prefixed alternative.