Join our Discord Community

Breadcrumb

Displays the path to the current resource using a hierarchy of links.

Loading component...

Installation

npx shadcn@latest add breadcrumb

Usage

import {
  Breadcrumb,
  BreadcrumbItem,
  BreadcrumbLink,
  BreadcrumbList,
  BreadcrumbPage,
  BreadcrumbSeparator,
} from "@/components/ui/breadcrumb"

export function BreadcrumbDemo() {
  return (
    <Breadcrumb>
      <BreadcrumbList>
        <BreadcrumbItem>
          <BreadcrumbLink>Home</BreadcrumbLink>
        </BreadcrumbItem>
        <BreadcrumbSeparator />
        <BreadcrumbItem>
          <BreadcrumbLink>Components</BreadcrumbLink>
        </BreadcrumbItem>
        <BreadcrumbSeparator />
        <BreadcrumbItem>
          <BreadcrumbPage>Breadcrumb</BreadcrumbPage>
        </BreadcrumbItem>
      </BreadcrumbList>
    </Breadcrumb>
  )
}

Simple Example

Loading component...

Examples

Custom Separator

Loading component...

With Dropdown

Loading component...

Collapsed

Loading component...

With Icons

Loading component...

Variations

Loading component...

API Reference

The root breadcrumb navigation container.

PropTypeDefaultDescription
classNamestring-Additional CSS classes for styling.
childrenReact.ReactNode-BreadcrumbList component.

The ordered list container for breadcrumb items.

PropTypeDefaultDescription
classNamestring-Additional CSS classes for styling.
childrenReact.ReactNode-BreadcrumbItem components with separators.

Individual breadcrumb item wrapper.

PropTypeDefaultDescription
classNamestring-Additional CSS classes for styling.
childrenReact.ReactNode-BreadcrumbLink, BreadcrumbPage, or custom content.

Navigational link within breadcrumb.

PropTypeDefaultDescription
asChildbooleanfalseRender as child component (useful for Next.js Link).
hrefstring-Link destination (when not using asChild).
classNamestring-Additional CSS classes for styling.
childrenReact.ReactNode-Link text or content.

Current page indicator (non-interactive).

PropTypeDefaultDescription
classNamestring-Additional CSS classes for styling.
childrenReact.ReactNode-Current page text or content.

Visual separator between breadcrumb items.

PropTypeDefaultDescription
classNamestring-Additional CSS classes for styling.
childrenReact.ReactNode<ChevronRight />Custom separator content (icon or text).

Ellipsis indicator for collapsed breadcrumbs.

PropTypeDefaultDescription
classNamestring-Additional CSS classes for styling.

Implementation Details

Architecture

Built with semantic HTML and ARIA attributes for accessibility:

  • Navigation Landmark: Uses <nav> with aria-label="breadcrumb"
  • Ordered List: Structured as <ol> for logical hierarchy
  • Current Page: Marked with aria-current="page" and role="link"
  • Separators: Hidden from screen readers with aria-hidden="true"

Component Structure

<Breadcrumb>                    {/* <nav aria-label="breadcrumb"> */}
  <BreadcrumbList>             {/* <ol> */}
    <BreadcrumbItem>           {/* <li> */}
      <BreadcrumbLink />       {/* <a> or custom component */}
    </BreadcrumbItem>
    <BreadcrumbSeparator />    {/* <li role="presentation"> */}
    <BreadcrumbItem>
      <BreadcrumbPage />       {/* <span aria-current="page"> */}
    </BreadcrumbItem>
  </BreadcrumbList>
</Breadcrumb>

Responsive Design

Breadcrumbs automatically wrap and scale:

  • Text Wrapping: Uses break-words for long paths
  • Flexible Spacing: Responsive gap sizing (gap-1.5 on mobile, gap-2.5 on desktop)
  • Icon Scaling: Separators sized appropriately (size-3.5)

Best Practices

Structure breadcrumbs to reflect logical navigation:

// Good - Clear hierarchy
<Breadcrumb>
  <BreadcrumbList>
    <BreadcrumbItem>
      <BreadcrumbLink href="/">Home</BreadcrumbLink>
    </BreadcrumbItem>
    <BreadcrumbSeparator />
    <BreadcrumbItem>
      <BreadcrumbLink href="/products">Products</BreadcrumbLink>
    </BreadcrumbItem>
    <BreadcrumbSeparator />
    <BreadcrumbItem>
      <BreadcrumbLink href="/products/laptops">Laptops</BreadcrumbLink>
    </BreadcrumbItem>
    <BreadcrumbSeparator />
    <BreadcrumbItem>
      <BreadcrumbPage>MacBook Pro</BreadcrumbPage>
    </BreadcrumbItem>
  </BreadcrumbList>
</Breadcrumb>

Use the asChild prop for framework-specific routing:

import Link from "next/link"

<BreadcrumbLink asChild>
  <Link href="/dashboard">Dashboard</Link>
</BreadcrumbLink>

Content Guidelines

  1. Keep labels concise: Use short, descriptive terms
  2. Avoid redundancy: Don't repeat the site name in every breadcrumb
  3. Use sentence case: Capitalize only the first letter
  4. Current page: Always use BreadcrumbPage for the current location

Common Use Cases

E-commerce Navigation

Product catalog and category navigation:

Loading component...

Documentation Site

Multi-level documentation navigation with icon home:

Loading component...

File System Navigation

File and folder navigation interface:

function FileBreadcrumb({ path }) {
  const pathSegments = path.split('/').filter(Boolean)
  
  return (
    <Breadcrumb>
      <BreadcrumbList>
        <BreadcrumbItem>
          <BreadcrumbLink asChild>
            <Link href="/files" className="flex items-center gap-2">
              <HomeIcon className="size-4" />
              Root
            </Link>
          </BreadcrumbLink>
        </BreadcrumbItem>
        {pathSegments.map((segment, index) => {
          const isLast = index === pathSegments.length - 1
          const href = `/files/${pathSegments.slice(0, index + 1).join('/')}`
          
          return (
            <React.Fragment key={index}>
              <BreadcrumbSeparator />
              <BreadcrumbItem>
                {isLast ? (
                  <BreadcrumbPage className="flex items-center gap-2">
                    <FileIcon className="size-4" />
                    {segment}
                  </BreadcrumbPage>
                ) : (
                  <BreadcrumbLink asChild>
                    <Link href={href} className="flex items-center gap-2">
                      <FolderIcon className="size-4" />
                      {segment}
                    </Link>
                  </BreadcrumbLink>
                )}
              </BreadcrumbItem>
            </React.Fragment>
          )
        })}
      </BreadcrumbList>
    </Breadcrumb>
  )
}

Advanced Patterns

Responsive Breadcrumbs

Handle long navigation paths gracefully:

function ResponsiveBreadcrumb({ items, maxItems = 3 }) {
  const [isExpanded, setIsExpanded] = useState(false)
  
  if (items.length <= maxItems) {
    return <NormalBreadcrumb items={items} />
  }
  
  const visibleItems = isExpanded 
    ? items 
    : [items[0], ...items.slice(-2)]
  
  return (
    <Breadcrumb>
      <BreadcrumbList>
        <BreadcrumbItem>
          <BreadcrumbLink asChild>
            <Link href={items[0].href}>{items[0].label}</Link>
          </BreadcrumbLink>
        </BreadcrumbItem>
        
        {!isExpanded && items.length > maxItems && (
          <>
            <BreadcrumbSeparator />
            <BreadcrumbItem>
              <button
                onClick={() => setIsExpanded(true)}
                className="flex items-center gap-1"
              >
                <BreadcrumbEllipsis />
              </button>
            </BreadcrumbItem>
          </>
        )}
        
        {/* Render remaining items */}
        {visibleItems.slice(1).map((item, index) => (
          <React.Fragment key={index}>
            <BreadcrumbSeparator />
            <BreadcrumbItem>
              {item.href ? (
                <BreadcrumbLink asChild>
                  <Link href={item.href}>{item.label}</Link>
                </BreadcrumbLink>
              ) : (
                <BreadcrumbPage>{item.label}</BreadcrumbPage>
              )}
            </BreadcrumbItem>
          </React.Fragment>
        ))}
      </BreadcrumbList>
    </Breadcrumb>
  )
}

Dynamic Breadcrumbs

Generate breadcrumbs from URL or route data:

function DynamicBreadcrumb() {
  const pathname = usePathname()
  const router = useRouter()
  
  const breadcrumbItems = useMemo(() => {
    const segments = pathname.split('/').filter(Boolean)
    
    return segments.map((segment, index) => {
      const href = '/' + segments.slice(0, index + 1).join('/')
      const label = segment.charAt(0).toUpperCase() + segment.slice(1)
      const isLast = index === segments.length - 1
      
      return { href: isLast ? null : href, label, isLast }
    })
  }, [pathname])
  
  return (
    <Breadcrumb>
      <BreadcrumbList>
        <BreadcrumbItem>
          <BreadcrumbLink asChild>
            <Link href="/">Home</Link>
          </BreadcrumbLink>
        </BreadcrumbItem>
        {breadcrumbItems.map((item, index) => (
          <React.Fragment key={index}>
            <BreadcrumbSeparator />
            <BreadcrumbItem>
              {item.isLast ? (
                <BreadcrumbPage>{item.label}</BreadcrumbPage>
              ) : (
                <BreadcrumbLink asChild>
                  <Link href={item.href!}>{item.label}</Link>
                </BreadcrumbLink>
              )}
            </BreadcrumbItem>
          </React.Fragment>
        ))}
      </BreadcrumbList>
    </Breadcrumb>
  )
}

Combine with DropdownMenu for additional navigation options:

function BreadcrumbWithMenu() {
  return (
    <Breadcrumb>
      <BreadcrumbList>
        <BreadcrumbItem>
          <BreadcrumbLink asChild>
            <Link href="/">Home</Link>
          </BreadcrumbLink>
        </BreadcrumbItem>
        <BreadcrumbSeparator />
        <BreadcrumbItem>
          <DropdownMenu>
            <DropdownMenuTrigger className="flex items-center gap-1">
              Products
              <ChevronDownIcon className="size-4" />
            </DropdownMenuTrigger>
            <DropdownMenuContent align="start">
              <DropdownMenuItem asChild>
                <Link href="/products/electronics">Electronics</Link>
              </DropdownMenuItem>
              <DropdownMenuItem asChild>
                <Link href="/products/clothing">Clothing</Link>
              </DropdownMenuItem>
              <DropdownMenuItem asChild>
                <Link href="/products/books">Books</Link>
              </DropdownMenuItem>
            </DropdownMenuContent>
          </DropdownMenu>
        </BreadcrumbItem>
        <BreadcrumbSeparator />
        <BreadcrumbItem>
          <BreadcrumbPage>MacBook Pro</BreadcrumbPage>
        </BreadcrumbItem>
      </BreadcrumbList>
    </Breadcrumb>
  )
}

Accessibility

Screen Reader Support

Breadcrumbs provide rich semantic information:

  • Navigation landmark: Announced as "breadcrumb navigation"
  • Ordered structure: Screen readers understand the hierarchy
  • Current location: Clearly identified with aria-current="page"

Keyboard Navigation

Standard link navigation applies:

  • Tab: Move between breadcrumb links
  • Enter/Space: Activate links
  • Arrow keys: Not used (standard link behavior)

ARIA Attributes

The component automatically handles:

// Automatically applied
<nav aria-label="breadcrumb">
  <ol>
    <li>
      <a href="/home">Home</a>
    </li>
    <li role="presentation" aria-hidden="true">
      <ChevronRightIcon />
    </li>
    <li>
      <span role="link" aria-disabled="true" aria-current="page">
        Current Page
      </span>
    </li>
  </ol>
</nav>

SEO Benefits

Search Engine Optimization

Breadcrumbs improve SEO through:

  1. Internal Linking: Creates natural link hierarchy
  2. Context Signals: Helps search engines understand site structure
  3. Rich Snippets: May appear in search results
  4. User Experience: Reduces bounce rate with better navigation

Structured Data

Consider adding JSON-LD structured data:

function SEOBreadcrumb({ items }) {
  const structuredData = {
    "@context": "https://schema.org",
    "@type": "BreadcrumbList",
    "itemListElement": items.map((item, index) => ({
      "@type": "ListItem",
      "position": index + 1,
      "name": item.label,
      "item": item.href ? `https://example.com${item.href}` : undefined
    }))
  }
  
  return (
    <>
      <script
        type="application/ld+json"
        dangerouslySetInnerHTML={{ __html: JSON.stringify(structuredData) }}
      />
      <Breadcrumb>
        {/* Breadcrumb implementation */}
      </Breadcrumb>
    </>
  )
}

Performance Considerations

Client-Side Navigation

Optimize for single-page applications:

// Use Next.js Link for client-side navigation
<BreadcrumbLink asChild>
  <Link href="/products" prefetch={false}>
    Products
  </Link>
</BreadcrumbLink>

Dynamic Loading

For large site structures, consider lazy loading:

function LazyBreadcrumb({ path }) {
  const [breadcrumbData, setBreadcrumbData] = useState(null)
  
  useEffect(() => {
    // Fetch breadcrumb data based on current path
    fetchBreadcrumbData(path).then(setBreadcrumbData)
  }, [path])
  
  if (!breadcrumbData) {
    return <BreadcrumbSkeleton />
  }
  
  return <Breadcrumb>{/* Render with data */}</Breadcrumb>
}

Troubleshooting

Common Issues

  1. Links not working: Ensure proper asChild usage with routing libraries
  2. Separators not aligned: Check icon sizing and container spacing
  3. Responsive issues: Verify text wrapping and gap classes
  4. Accessibility warnings: Ensure current page uses BreadcrumbPage

Debugging

// Add visual debugging
<BreadcrumbList className="border border-red-200 bg-red-50">
  {/* Breadcrumb items */}
</BreadcrumbList>

// Log breadcrumb structure
console.log('Breadcrumb path:', pathname.split('/'))

Integration Examples

With App Router

// app/products/[category]/[id]/page.tsx
export default function ProductPage({ params }) {
  return (
    <div>
      <Breadcrumb>
        <BreadcrumbList>
          <BreadcrumbItem>
            <BreadcrumbLink asChild>
              <Link href="/">Home</Link>
            </BreadcrumbLink>
          </BreadcrumbItem>
          <BreadcrumbSeparator />
          <BreadcrumbItem>
            <BreadcrumbLink asChild>
              <Link href="/products">Products</Link>
            </BreadcrumbLink>
          </BreadcrumbItem>
          <BreadcrumbSeparator />
          <BreadcrumbItem>
            <BreadcrumbLink asChild>
              <Link href={`/products/${params.category}`}>
                {params.category}
              </Link>
            </BreadcrumbLink>
          </BreadcrumbItem>
          <BreadcrumbSeparator />
          <BreadcrumbItem>
            <BreadcrumbPage>{params.id}</BreadcrumbPage>
          </BreadcrumbItem>
        </BreadcrumbList>
      </Breadcrumb>
    </div>
  )
}