22 / 39
All 39 in 39 Tailwind CSS Breadcrumbs
- 01Tailwind Accessible Breadcrumb with Schema.org Microdata & ARIA
- 02Tailwind Responsive Collapsing Breadcrumb Bar with Container Queries
- 03Tailwind Adaptive Light & Dark Mode Breadcrumb Bar with Theme Tokens
- 04Tailwind E-Commerce Filter & Facet Breadcrumb with Removable Chips
- 05Tailwind Glassmorphism Floating Breadcrumb Pill with Shimmer Sweep
- 06Tailwind Neumorphic Soft UI Breadcrumb with Dual Box Shadows
- 07Tailwind Sticky Scroll-Shrink Breadcrumb Header with Scroll-Driven Animation
- 08Tailwind Material Design Flat Breadcrumb Bar with Ink Ripple
- 09Tailwind Isometric 3D Layered Breadcrumb with Extruded Tiles
- 10Tailwind Breadcrumb Bar with Built-In Dropdown Sibling Menus
- 11Tailwind Full-Width Block-Style Segmented Breadcrumb Bar
- 12Tailwind Accent-Colour Toggle Breadcrumb with Persisted Theme
- 13Tailwind Seamless Arrow-Cutout Breadcrumb Trail with clip-path
- 14Tailwind Compact Icon-Only Home Node Breadcrumb Bar
- 15Tailwind Segmented Rounded-Outline Pill Breadcrumb
- 16Tailwind Neumorphic Soft Inset-Shadow Breadcrumb Channel
- 17Tailwind CSS Grid Auto-Fitting Responsive Breadcrumb Trail
- 18Tailwind Holographic Shimmer Web3 Breadcrumb with Animated @property
- 19Tailwind SaaS Gradient-Text Breadcrumb Bar with Animated Clip
- 20Tailwind Marketplace Filter-Chip Breadcrumb with Icon Chips
- 21Tailwind Editorial Breadcrumb with Animated SVG Wave Underline
- 22Tailwind Developer Docs Breadcrumb with One-Click Path Copy
- 23Tailwind Modern Arrow Breadcrumb Bar using clip-path Polygons
- 24Tailwind Multi-Line Aligned Breadcrumb Layout with CSS Subgrid
- 25Tailwind Breadcrumb Links with Animated Underline Glow
- 26Tailwind Minimalist Breadcrumb with Swappable Masked SVG Separators
- 27Tailwind Multi-Step Checkout & Wizard Breadcrumb Indicator
- 28Tailwind Ribbon-Style Chevron Breadcrumb Trail
- 29Tailwind Pill-Shape Badge Breadcrumb Bar
- 30Tailwind Clean Line-Separator Minimalist Breadcrumbs
- 31Tailwind Gradient Background Glow Breadcrumb Bar
- 32Tailwind Floating Card Shadow Breadcrumb Navigation
- 33Tailwind Truncated Ellipsis Compact Mobile Breadcrumb
- 34Tailwind Inline Bullet-Dot Separator Breadcrumb
- 35Tailwind Skewed Parallelogram Breadcrumb Bar
- 36Tailwind Outline Border-Only Geometric Breadcrumbs
- 37Tailwind Circular Icon & Numbered Step Breadcrumbs
- 38Tailwind Frosted Glass Dark UI Breadcrumb Component
- 39Tailwind Micro-Interaction Animated Hover Breadcrumbs
Tailwind Developer Docs Breadcrumb with One-Click Path Copy
The terminal-flavoured docs trail: monospace crumbs, slash separators, and a copy button that puts the whole path on the clipboard for pasting into a PR or a ticket. The copied state is a data-copied attribute, so the icon swap and the button's own recolour both read it through variants.
Untitled UI Pro: 5,000+ React + Tailwind CSS v4 components · from $349 one-time
Untitled UI React · Affiliate link
The code
<section class="tbc-22 w-full min-h-svh grid place-items-center px-5 py-8 font-tbc22-mono text-tbc22-ink bg-[radial-gradient(1200px_600px_at_50%_-10%,oklch(0.28_0.05_265/0.55),transparent_60%),var(--color-tbc22-bg)]">
<nav aria-label="Documentation breadcrumb" class="inline-flex items-center gap-2 max-w-full overflow-x-auto pl-4 pr-2 py-2 rounded-xl bg-tbc22-surface border border-tbc22-edge shadow-[inset_0_1px_0_oklch(1_0_0/0.04),0_10px_30px_-12px_oklch(0_0_0/0.6)] text-[15px]/[1.2] [scrollbar-width:thin]">
<ol class="inline-flex flex-nowrap items-center gap-1 list-none m-0 p-0">
<li class="inline-flex items-center whitespace-nowrap"><a href="#" class="px-2 py-1.5 rounded-md text-tbc22-mut no-underline transition-colors duration-150 hover:text-tbc22-hover hover:bg-[color-mix(in_oklch,var(--color-tbc22-acc)_8%,transparent)] focus-visible:outline-2 focus-visible:outline-tbc22-acc focus-visible:outline-offset-2">docs</a></li>
<li class="inline-flex items-center whitespace-nowrap before:content-['/'] before:px-1 before:select-none before:text-tbc22-sep"><a href="#" class="px-2 py-1.5 rounded-md text-tbc22-mut no-underline transition-colors duration-150 hover:text-tbc22-hover hover:bg-[color-mix(in_oklch,var(--color-tbc22-acc)_8%,transparent)] focus-visible:outline-2 focus-visible:outline-tbc22-acc focus-visible:outline-offset-2">api</a></li>
<li class="inline-flex items-center whitespace-nowrap before:content-['/'] before:px-1 before:select-none before:text-tbc22-sep"><a href="#" class="px-2 py-1.5 rounded-md text-tbc22-mut no-underline transition-colors duration-150 hover:text-tbc22-hover hover:bg-[color-mix(in_oklch,var(--color-tbc22-acc)_8%,transparent)] focus-visible:outline-2 focus-visible:outline-tbc22-acc focus-visible:outline-offset-2">authentication</a></li>
<li class="inline-flex items-center whitespace-nowrap before:content-['/'] before:px-1 before:select-none before:text-tbc22-sep"><a href="#" aria-current="page" class="px-2 py-1.5 rounded-md font-semibold cursor-default no-underline text-tbc22-acc bg-[color-mix(in_oklch,var(--color-tbc22-acc)_12%,transparent)] focus-visible:outline-2 focus-visible:outline-tbc22-acc focus-visible:outline-offset-2">oauth2</a></li>
</ol>
<button type="button" aria-label="Copy path to clipboard" data-path="docs/api/authentication/oauth2" class="group relative grid place-items-center flex-none w-11 h-11 rounded-lg cursor-pointer appearance-none text-tbc22-ink bg-[color-mix(in_oklch,var(--color-tbc22-surface)_70%,oklch(0.28_0.02_260))] border border-tbc22-edge transition-[background-color,color,border-color,scale] duration-150 hover:text-white hover:border-[color-mix(in_oklch,var(--color-tbc22-acc)_40%,var(--color-tbc22-edge))] hover:bg-[color-mix(in_oklch,var(--color-tbc22-acc)_10%,var(--color-tbc22-surface))] active:scale-96 focus-visible:outline-2 focus-visible:outline-tbc22-acc focus-visible:outline-offset-2 data-copied:border-[color-mix(in_oklch,var(--color-tbc22-acc)_60%,var(--color-tbc22-edge))] data-copied:bg-[color-mix(in_oklch,var(--color-tbc22-acc)_15%,var(--color-tbc22-surface))] motion-reduce:transition-none motion-reduce:active:scale-100">
<svg aria-hidden="true" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" class="absolute inset-0 m-auto w-4.5 h-4.5 transition-[opacity,scale] duration-200 group-data-copied:opacity-0 group-data-copied:scale-60"><rect x="9" y="9" width="13" height="13" rx="2"/><path d="M5 15V5a2 2 0 0 1 2-2h10"/></svg>
<svg aria-hidden="true" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" class="absolute inset-0 m-auto w-4.5 h-4.5 opacity-0 scale-60 text-tbc22-acc transition-[opacity,scale] duration-200 group-data-copied:opacity-100 group-data-copied:scale-100"><path d="m5 12 5 5L20 7"/></svg>
</button>
<span role="status" aria-live="polite" aria-atomic="true" class="sr-only"></span>
</nav>
</section><section class="tbc-22 w-full min-h-svh grid place-items-center px-5 py-8 font-tbc22-mono text-tbc22-ink bg-[radial-gradient(1200px_600px_at_50%_-10%,oklch(0.28_0.05_265/0.55),transparent_60%),var(--color-tbc22-bg)]">
<nav aria-label="Documentation breadcrumb" class="inline-flex items-center gap-2 max-w-full overflow-x-auto pl-4 pr-2 py-2 rounded-xl bg-tbc22-surface border border-tbc22-edge shadow-[inset_0_1px_0_oklch(1_0_0/0.04),0_10px_30px_-12px_oklch(0_0_0/0.6)] text-[15px]/[1.2] [scrollbar-width:thin]">
<ol class="inline-flex flex-nowrap items-center gap-1 list-none m-0 p-0">
<li class="inline-flex items-center whitespace-nowrap"><a href="#" class="px-2 py-1.5 rounded-md text-tbc22-mut no-underline transition-colors duration-150 hover:text-tbc22-hover hover:bg-[color-mix(in_oklch,var(--color-tbc22-acc)_8%,transparent)] focus-visible:outline-2 focus-visible:outline-tbc22-acc focus-visible:outline-offset-2">docs</a></li>
<li class="inline-flex items-center whitespace-nowrap before:content-['/'] before:px-1 before:select-none before:text-tbc22-sep"><a href="#" class="px-2 py-1.5 rounded-md text-tbc22-mut no-underline transition-colors duration-150 hover:text-tbc22-hover hover:bg-[color-mix(in_oklch,var(--color-tbc22-acc)_8%,transparent)] focus-visible:outline-2 focus-visible:outline-tbc22-acc focus-visible:outline-offset-2">api</a></li>
<li class="inline-flex items-center whitespace-nowrap before:content-['/'] before:px-1 before:select-none before:text-tbc22-sep"><a href="#" class="px-2 py-1.5 rounded-md text-tbc22-mut no-underline transition-colors duration-150 hover:text-tbc22-hover hover:bg-[color-mix(in_oklch,var(--color-tbc22-acc)_8%,transparent)] focus-visible:outline-2 focus-visible:outline-tbc22-acc focus-visible:outline-offset-2">authentication</a></li>
<li class="inline-flex items-center whitespace-nowrap before:content-['/'] before:px-1 before:select-none before:text-tbc22-sep"><a href="#" aria-current="page" class="px-2 py-1.5 rounded-md font-semibold cursor-default no-underline text-tbc22-acc bg-[color-mix(in_oklch,var(--color-tbc22-acc)_12%,transparent)] focus-visible:outline-2 focus-visible:outline-tbc22-acc focus-visible:outline-offset-2">oauth2</a></li>
</ol>
<button type="button" aria-label="Copy path to clipboard" data-path="docs/api/authentication/oauth2" class="group relative grid place-items-center flex-none w-11 h-11 rounded-lg cursor-pointer appearance-none text-tbc22-ink bg-[color-mix(in_oklch,var(--color-tbc22-surface)_70%,oklch(0.28_0.02_260))] border border-tbc22-edge transition-[background-color,color,border-color,scale] duration-150 hover:text-white hover:border-[color-mix(in_oklch,var(--color-tbc22-acc)_40%,var(--color-tbc22-edge))] hover:bg-[color-mix(in_oklch,var(--color-tbc22-acc)_10%,var(--color-tbc22-surface))] active:scale-96 focus-visible:outline-2 focus-visible:outline-tbc22-acc focus-visible:outline-offset-2 data-copied:border-[color-mix(in_oklch,var(--color-tbc22-acc)_60%,var(--color-tbc22-edge))] data-copied:bg-[color-mix(in_oklch,var(--color-tbc22-acc)_15%,var(--color-tbc22-surface))] motion-reduce:transition-none motion-reduce:active:scale-100">
<svg aria-hidden="true" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" class="absolute inset-0 m-auto w-4.5 h-4.5 transition-[opacity,scale] duration-200 group-data-copied:opacity-0 group-data-copied:scale-60"><rect x="9" y="9" width="13" height="13" rx="2"/><path d="M5 15V5a2 2 0 0 1 2-2h10"/></svg>
<svg aria-hidden="true" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" class="absolute inset-0 m-auto w-4.5 h-4.5 opacity-0 scale-60 text-tbc22-acc transition-[opacity,scale] duration-200 group-data-copied:opacity-100 group-data-copied:scale-100"><path d="m5 12 5 5L20 7"/></svg>
</button>
<span role="status" aria-live="polite" aria-atomic="true" class="sr-only"></span>
</nav>
</section>@import "tailwindcss";
@theme {
--color-tbc22-bg: #1e2028;
--color-tbc22-bg: oklch(0.16 0.02 260);
--color-tbc22-surface: #2a2d36;
--color-tbc22-surface: oklch(0.21 0.02 260);
--color-tbc22-edge: #454955;
--color-tbc22-edge: oklch(0.32 0.02 260 / 0.6);
--color-tbc22-ink: #cfd2db;
--color-tbc22-ink: oklch(0.82 0.02 260);
--color-tbc22-mut: #9ba0ad;
--color-tbc22-mut: oklch(0.68 0.02 260);
--color-tbc22-hover: #eceef4;
--color-tbc22-hover: oklch(0.92 0.02 260);
--color-tbc22-sep: #6b7080;
--color-tbc22-sep: oklch(0.5 0.02 260);
--color-tbc22-acc: #c79df5;
--color-tbc22-acc: oklch(0.78 0.17 300);
--font-tbc22-mono: 'JetBrains Mono', ui-monospace, 'SF Mono', Menlo, monospace;
}
.tbc-22 {
width: 100%;
min-height: 100svh;
}@import "tailwindcss";
@theme {
--color-tbc22-bg: #1e2028;
--color-tbc22-bg: oklch(0.16 0.02 260);
--color-tbc22-surface: #2a2d36;
--color-tbc22-surface: oklch(0.21 0.02 260);
--color-tbc22-edge: #454955;
--color-tbc22-edge: oklch(0.32 0.02 260 / 0.6);
--color-tbc22-ink: #cfd2db;
--color-tbc22-ink: oklch(0.82 0.02 260);
--color-tbc22-mut: #9ba0ad;
--color-tbc22-mut: oklch(0.68 0.02 260);
--color-tbc22-hover: #eceef4;
--color-tbc22-hover: oklch(0.92 0.02 260);
--color-tbc22-sep: #6b7080;
--color-tbc22-sep: oklch(0.5 0.02 260);
--color-tbc22-acc: #c79df5;
--color-tbc22-acc: oklch(0.78 0.17 300);
--font-tbc22-mono: 'JetBrains Mono', ui-monospace, 'SF Mono', Menlo, monospace;
}
.tbc-22 {
width: 100%;
min-height: 100svh;
}(function () {
document.querySelectorAll('.tbc-22 button[data-path]').forEach(function (btn) {
if (btn.dataset.bound) return; btn.dataset.bound = '1';
var live = btn.parentElement.querySelector('[role="status"]'), timer;
btn.addEventListener('click', function () {
navigator.clipboard.writeText(btn.dataset.path).then(function () {
btn.toggleAttribute('data-copied', true);
if (live) live.textContent = 'Path copied to clipboard';
clearTimeout(timer);
timer = setTimeout(function () {
btn.removeAttribute('data-copied');
if (live) live.textContent = '';
}, 1200);
}).catch(function () {
if (live) live.textContent = 'Copy failed — clipboard unavailable';
});
});
});
})();(function () {
document.querySelectorAll('.tbc-22 button[data-path]').forEach(function (btn) {
if (btn.dataset.bound) return; btn.dataset.bound = '1';
var live = btn.parentElement.querySelector('[role="status"]'), timer;
btn.addEventListener('click', function () {
navigator.clipboard.writeText(btn.dataset.path).then(function () {
btn.toggleAttribute('data-copied', true);
if (live) live.textContent = 'Path copied to clipboard';
clearTimeout(timer);
timer = setTimeout(function () {
btn.removeAttribute('data-copied');
if (live) live.textContent = '';
}, 1200);
}).catch(function () {
if (live) live.textContent = 'Copy failed — clipboard unavailable';
});
});
});
})();Setup — do this once per project
Skip this if your project already runs Tailwind v4.
<script src="https://cdn.jsdelivr.net/npm/@tailwindcss/browser@4"></script>
<script src="https://cdn.jsdelivr.net/npm/@tailwindcss/browser@4"></script>Compiles in the browser — perfect for a CodePen or a quick test, not for production.
npm install tailwindcss @tailwindcss/vite
npm install tailwindcss @tailwindcss/vite// vite.config.js ("type": "module" in package.json)
import { defineConfig } from 'vite'
import tailwindcss from '@tailwindcss/vite'
export default defineConfig({
plugins: [tailwindcss()],
})// vite.config.js ("type": "module" in package.json)
import { defineConfig } from 'vite'
import tailwindcss from '@tailwindcss/vite'
export default defineConfig({
plugins: [tailwindcss()],
})Any v4 setup works — Vite, PostCSS or the CLI. Nothing in this demo is bundler-specific.
@import "tailwindcss";
@theme {
--color-tbc22-bg: #1e2028;
--color-tbc22-bg: oklch(0.16 0.02 260);
--color-tbc22-surface: #2a2d36;
--color-tbc22-surface: oklch(0.21 0.02 260);
--color-tbc22-edge: #454955;
--color-tbc22-edge: oklch(0.32 0.02 260 / 0.6);
--color-tbc22-ink: #cfd2db;
--color-tbc22-ink: oklch(0.82 0.02 260);
--color-tbc22-mut: #9ba0ad;
--color-tbc22-mut: oklch(0.68 0.02 260);
--color-tbc22-hover: #eceef4;
--color-tbc22-hover: oklch(0.92 0.02 260);
--color-tbc22-sep: #6b7080;
--color-tbc22-sep: oklch(0.5 0.02 260);
--color-tbc22-acc: #c79df5;
--color-tbc22-acc: oklch(0.78 0.17 300);
--font-tbc22-mono: 'JetBrains Mono', ui-monospace, 'SF Mono', Menlo, monospace;
}
.tbc-22 {
width: 100%;
min-height: 100svh;
}@import "tailwindcss";
@theme {
--color-tbc22-bg: #1e2028;
--color-tbc22-bg: oklch(0.16 0.02 260);
--color-tbc22-surface: #2a2d36;
--color-tbc22-surface: oklch(0.21 0.02 260);
--color-tbc22-edge: #454955;
--color-tbc22-edge: oklch(0.32 0.02 260 / 0.6);
--color-tbc22-ink: #cfd2db;
--color-tbc22-ink: oklch(0.82 0.02 260);
--color-tbc22-mut: #9ba0ad;
--color-tbc22-mut: oklch(0.68 0.02 260);
--color-tbc22-hover: #eceef4;
--color-tbc22-hover: oklch(0.92 0.02 260);
--color-tbc22-sep: #6b7080;
--color-tbc22-sep: oklch(0.5 0.02 260);
--color-tbc22-acc: #c79df5;
--color-tbc22-acc: oklch(0.78 0.17 300);
--font-tbc22-mono: 'JetBrains Mono', ui-monospace, 'SF Mono', Menlo, monospace;
}
.tbc-22 {
width: 100%;
min-height: 100svh;
}<link rel="preconnect" href="https://fonts.googleapis.com"> <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin> <link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@400;500;600&display=swap">
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@400;500;600&display=swap">What changed in the port
Which parts became utilities, which stayed CSS, and why.
- An
.is-copiedclass plus three descendant rules become onedata-copiedattribute read bydata-copied:on the button andgroup-data-copied:on both icons. The script no longer knows anything about presentation. - The muted crumb ink was lightened from
oklch(0.58)to0.68: on the dark surface the original sat at roughly 3.6:1, below AA for 15px text. - UI change from the CSS original: a copy FAILURE is now announced too. The original caught the rejection and said nothing, which on
http://meant the button looked broken with no explanation.
Here's a working CSS demo from CodeFronts. Use it as-is or adapt to your framework. All classes are scoped under a unique prefix so the code won't collide with your existing styles. MIT licensed.
Demo: Tailwind Developer Docs Breadcrumb with One-Click Path Copy
Source: https://codefronts.com/navigation/tailwind-css-breadcrumbs/tailwind-developer-docs-breadcrumb-one-click-path-copy/
The terminal-flavoured docs trail: monospace crumbs, slash separators, and a copy button that puts the whole path on the clipboard for pasting into a PR or a ticket. The copied state is a data-copied attribute, so the icon swap and the button's own recolour both read it through variants.
## HTML
```html
<section class="tbc-22 w-full min-h-svh grid place-items-center px-5 py-8 font-tbc22-mono text-tbc22-ink bg-[radial-gradient(1200px_600px_at_50%_-10%,oklch(0.28_0.05_265/0.55),transparent_60%),var(--color-tbc22-bg)]">
<nav aria-label="Documentation breadcrumb" class="inline-flex items-center gap-2 max-w-full overflow-x-auto pl-4 pr-2 py-2 rounded-xl bg-tbc22-surface border border-tbc22-edge shadow-[inset_0_1px_0_oklch(1_0_0/0.04),0_10px_30px_-12px_oklch(0_0_0/0.6)] text-[15px]/[1.2] [scrollbar-width:thin]">
<ol class="inline-flex flex-nowrap items-center gap-1 list-none m-0 p-0">
<li class="inline-flex items-center whitespace-nowrap"><a href="#" class="px-2 py-1.5 rounded-md text-tbc22-mut no-underline transition-colors duration-150 hover:text-tbc22-hover hover:bg-[color-mix(in_oklch,var(--color-tbc22-acc)_8%,transparent)] focus-visible:outline-2 focus-visible:outline-tbc22-acc focus-visible:outline-offset-2">docs</a></li>
<li class="inline-flex items-center whitespace-nowrap before:content-['/'] before:px-1 before:select-none before:text-tbc22-sep"><a href="#" class="px-2 py-1.5 rounded-md text-tbc22-mut no-underline transition-colors duration-150 hover:text-tbc22-hover hover:bg-[color-mix(in_oklch,var(--color-tbc22-acc)_8%,transparent)] focus-visible:outline-2 focus-visible:outline-tbc22-acc focus-visible:outline-offset-2">api</a></li>
<li class="inline-flex items-center whitespace-nowrap before:content-['/'] before:px-1 before:select-none before:text-tbc22-sep"><a href="#" class="px-2 py-1.5 rounded-md text-tbc22-mut no-underline transition-colors duration-150 hover:text-tbc22-hover hover:bg-[color-mix(in_oklch,var(--color-tbc22-acc)_8%,transparent)] focus-visible:outline-2 focus-visible:outline-tbc22-acc focus-visible:outline-offset-2">authentication</a></li>
<li class="inline-flex items-center whitespace-nowrap before:content-['/'] before:px-1 before:select-none before:text-tbc22-sep"><a href="#" aria-current="page" class="px-2 py-1.5 rounded-md font-semibold cursor-default no-underline text-tbc22-acc bg-[color-mix(in_oklch,var(--color-tbc22-acc)_12%,transparent)] focus-visible:outline-2 focus-visible:outline-tbc22-acc focus-visible:outline-offset-2">oauth2</a></li>
</ol>
<button type="button" aria-label="Copy path to clipboard" data-path="docs/api/authentication/oauth2" class="group relative grid place-items-center flex-none w-11 h-11 rounded-lg cursor-pointer appearance-none text-tbc22-ink bg-[color-mix(in_oklch,var(--color-tbc22-surface)_70%,oklch(0.28_0.02_260))] border border-tbc22-edge transition-[background-color,color,border-color,scale] duration-150 hover:text-white hover:border-[color-mix(in_oklch,var(--color-tbc22-acc)_40%,var(--color-tbc22-edge))] hover:bg-[color-mix(in_oklch,var(--color-tbc22-acc)_10%,var(--color-tbc22-surface))] active:scale-96 focus-visible:outline-2 focus-visible:outline-tbc22-acc focus-visible:outline-offset-2 data-copied:border-[color-mix(in_oklch,var(--color-tbc22-acc)_60%,var(--color-tbc22-edge))] data-copied:bg-[color-mix(in_oklch,var(--color-tbc22-acc)_15%,var(--color-tbc22-surface))] motion-reduce:transition-none motion-reduce:active:scale-100">
<svg aria-hidden="true" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" class="absolute inset-0 m-auto w-4.5 h-4.5 transition-[opacity,scale] duration-200 group-data-copied:opacity-0 group-data-copied:scale-60"><rect x="9" y="9" width="13" height="13" rx="2"/><path d="M5 15V5a2 2 0 0 1 2-2h10"/></svg>
<svg aria-hidden="true" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" class="absolute inset-0 m-auto w-4.5 h-4.5 opacity-0 scale-60 text-tbc22-acc transition-[opacity,scale] duration-200 group-data-copied:opacity-100 group-data-copied:scale-100"><path d="m5 12 5 5L20 7"/></svg>
</button>
<span role="status" aria-live="polite" aria-atomic="true" class="sr-only"></span>
</nav>
</section>
```
## CSS
```css
@import "tailwindcss";
@theme {
--color-tbc22-bg: #1e2028;
--color-tbc22-bg: oklch(0.16 0.02 260);
--color-tbc22-surface: #2a2d36;
--color-tbc22-surface: oklch(0.21 0.02 260);
--color-tbc22-edge: #454955;
--color-tbc22-edge: oklch(0.32 0.02 260 / 0.6);
--color-tbc22-ink: #cfd2db;
--color-tbc22-ink: oklch(0.82 0.02 260);
--color-tbc22-mut: #9ba0ad;
--color-tbc22-mut: oklch(0.68 0.02 260);
--color-tbc22-hover: #eceef4;
--color-tbc22-hover: oklch(0.92 0.02 260);
--color-tbc22-sep: #6b7080;
--color-tbc22-sep: oklch(0.5 0.02 260);
--color-tbc22-acc: #c79df5;
--color-tbc22-acc: oklch(0.78 0.17 300);
--font-tbc22-mono: 'JetBrains Mono', ui-monospace, 'SF Mono', Menlo, monospace;
}
.tbc-22 {
width: 100%;
min-height: 100svh;
}
```
## JavaScript
```js
(function () {
document.querySelectorAll('.tbc-22 button[data-path]').forEach(function (btn) {
if (btn.dataset.bound) return; btn.dataset.bound = '1';
var live = btn.parentElement.querySelector('[role="status"]'), timer;
btn.addEventListener('click', function () {
navigator.clipboard.writeText(btn.dataset.path).then(function () {
btn.toggleAttribute('data-copied', true);
if (live) live.textContent = 'Path copied to clipboard';
clearTimeout(timer);
timer = setTimeout(function () {
btn.removeAttribute('data-copied');
if (live) live.textContent = '';
}, 1200);
}).catch(function () {
if (live) live.textContent = 'Copy failed — clipboard unavailable';
});
});
});
})();
```Here's a working CSS demo from CodeFronts. Use it as-is or adapt to your framework. All classes are scoped under a unique prefix so the code won't collide with your existing styles. MIT licensed.
Demo: Tailwind Developer Docs Breadcrumb with One-Click Path Copy
Source: https://codefronts.com/navigation/tailwind-css-breadcrumbs/tailwind-developer-docs-breadcrumb-one-click-path-copy/
The terminal-flavoured docs trail: monospace crumbs, slash separators, and a copy button that puts the whole path on the clipboard for pasting into a PR or a ticket. The copied state is a data-copied attribute, so the icon swap and the button's own recolour both read it through variants.
## HTML
```html
<section class="tbc-22 w-full min-h-svh grid place-items-center px-5 py-8 font-tbc22-mono text-tbc22-ink bg-[radial-gradient(1200px_600px_at_50%_-10%,oklch(0.28_0.05_265/0.55),transparent_60%),var(--color-tbc22-bg)]">
<nav aria-label="Documentation breadcrumb" class="inline-flex items-center gap-2 max-w-full overflow-x-auto pl-4 pr-2 py-2 rounded-xl bg-tbc22-surface border border-tbc22-edge shadow-[inset_0_1px_0_oklch(1_0_0/0.04),0_10px_30px_-12px_oklch(0_0_0/0.6)] text-[15px]/[1.2] [scrollbar-width:thin]">
<ol class="inline-flex flex-nowrap items-center gap-1 list-none m-0 p-0">
<li class="inline-flex items-center whitespace-nowrap"><a href="#" class="px-2 py-1.5 rounded-md text-tbc22-mut no-underline transition-colors duration-150 hover:text-tbc22-hover hover:bg-[color-mix(in_oklch,var(--color-tbc22-acc)_8%,transparent)] focus-visible:outline-2 focus-visible:outline-tbc22-acc focus-visible:outline-offset-2">docs</a></li>
<li class="inline-flex items-center whitespace-nowrap before:content-['/'] before:px-1 before:select-none before:text-tbc22-sep"><a href="#" class="px-2 py-1.5 rounded-md text-tbc22-mut no-underline transition-colors duration-150 hover:text-tbc22-hover hover:bg-[color-mix(in_oklch,var(--color-tbc22-acc)_8%,transparent)] focus-visible:outline-2 focus-visible:outline-tbc22-acc focus-visible:outline-offset-2">api</a></li>
<li class="inline-flex items-center whitespace-nowrap before:content-['/'] before:px-1 before:select-none before:text-tbc22-sep"><a href="#" class="px-2 py-1.5 rounded-md text-tbc22-mut no-underline transition-colors duration-150 hover:text-tbc22-hover hover:bg-[color-mix(in_oklch,var(--color-tbc22-acc)_8%,transparent)] focus-visible:outline-2 focus-visible:outline-tbc22-acc focus-visible:outline-offset-2">authentication</a></li>
<li class="inline-flex items-center whitespace-nowrap before:content-['/'] before:px-1 before:select-none before:text-tbc22-sep"><a href="#" aria-current="page" class="px-2 py-1.5 rounded-md font-semibold cursor-default no-underline text-tbc22-acc bg-[color-mix(in_oklch,var(--color-tbc22-acc)_12%,transparent)] focus-visible:outline-2 focus-visible:outline-tbc22-acc focus-visible:outline-offset-2">oauth2</a></li>
</ol>
<button type="button" aria-label="Copy path to clipboard" data-path="docs/api/authentication/oauth2" class="group relative grid place-items-center flex-none w-11 h-11 rounded-lg cursor-pointer appearance-none text-tbc22-ink bg-[color-mix(in_oklch,var(--color-tbc22-surface)_70%,oklch(0.28_0.02_260))] border border-tbc22-edge transition-[background-color,color,border-color,scale] duration-150 hover:text-white hover:border-[color-mix(in_oklch,var(--color-tbc22-acc)_40%,var(--color-tbc22-edge))] hover:bg-[color-mix(in_oklch,var(--color-tbc22-acc)_10%,var(--color-tbc22-surface))] active:scale-96 focus-visible:outline-2 focus-visible:outline-tbc22-acc focus-visible:outline-offset-2 data-copied:border-[color-mix(in_oklch,var(--color-tbc22-acc)_60%,var(--color-tbc22-edge))] data-copied:bg-[color-mix(in_oklch,var(--color-tbc22-acc)_15%,var(--color-tbc22-surface))] motion-reduce:transition-none motion-reduce:active:scale-100">
<svg aria-hidden="true" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" class="absolute inset-0 m-auto w-4.5 h-4.5 transition-[opacity,scale] duration-200 group-data-copied:opacity-0 group-data-copied:scale-60"><rect x="9" y="9" width="13" height="13" rx="2"/><path d="M5 15V5a2 2 0 0 1 2-2h10"/></svg>
<svg aria-hidden="true" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" class="absolute inset-0 m-auto w-4.5 h-4.5 opacity-0 scale-60 text-tbc22-acc transition-[opacity,scale] duration-200 group-data-copied:opacity-100 group-data-copied:scale-100"><path d="m5 12 5 5L20 7"/></svg>
</button>
<span role="status" aria-live="polite" aria-atomic="true" class="sr-only"></span>
</nav>
</section>
```
## CSS
```css
@import "tailwindcss";
@theme {
--color-tbc22-bg: #1e2028;
--color-tbc22-bg: oklch(0.16 0.02 260);
--color-tbc22-surface: #2a2d36;
--color-tbc22-surface: oklch(0.21 0.02 260);
--color-tbc22-edge: #454955;
--color-tbc22-edge: oklch(0.32 0.02 260 / 0.6);
--color-tbc22-ink: #cfd2db;
--color-tbc22-ink: oklch(0.82 0.02 260);
--color-tbc22-mut: #9ba0ad;
--color-tbc22-mut: oklch(0.68 0.02 260);
--color-tbc22-hover: #eceef4;
--color-tbc22-hover: oklch(0.92 0.02 260);
--color-tbc22-sep: #6b7080;
--color-tbc22-sep: oklch(0.5 0.02 260);
--color-tbc22-acc: #c79df5;
--color-tbc22-acc: oklch(0.78 0.17 300);
--font-tbc22-mono: 'JetBrains Mono', ui-monospace, 'SF Mono', Menlo, monospace;
}
.tbc-22 {
width: 100%;
min-height: 100svh;
}
```
## JavaScript
```js
(function () {
document.querySelectorAll('.tbc-22 button[data-path]').forEach(function (btn) {
if (btn.dataset.bound) return; btn.dataset.bound = '1';
var live = btn.parentElement.querySelector('[role="status"]'), timer;
btn.addEventListener('click', function () {
navigator.clipboard.writeText(btn.dataset.path).then(function () {
btn.toggleAttribute('data-copied', true);
if (live) live.textContent = 'Path copied to clipboard';
clearTimeout(timer);
timer = setTimeout(function () {
btn.removeAttribute('data-copied');
if (live) live.textContent = '';
}, 1200);
}).catch(function () {
if (live) live.textContent = 'Copy failed — clipboard unavailable';
});
});
});
})();
```How this works
The state is an attribute, again. The CSS version toggled an .is-copied class and wrote three descendant rules. Here the script sets data-copied; the button restyles itself with data-copied:, and both icons read group-data-copied:. Restyling the confirmation never means touching the script.
Announcement is not optional. A checkmark is invisible to a screen-reader user. The live region says "Path copied to clipboard" and clears after 1.2s, which is the same lifetime as the visual state.
The path is one string. It lives in a data-path attribute on the button rather than in the script, so the same controller works for any trail on the page.
Make it yours
- Separator:
before:content-['/']on the crumbs — swap for›if the trail is not path-shaped. - Confirmation lifetime: the
1200in the script, matched by nothing in the CSS (the transition handles itself). - Accent:
--color-tbc22-accdrives the current crumb, the copied state and every focus ring.
Gotchas — read before shipping
navigator.clipboardrequires a secure context; onhttp://it rejects and the demo fails silently. Add a fallback<textarea>if you support intranet HTTP.- Do not put the status text inside the button — it would change the button's accessible name mid-interaction.
- Absolutely stacked icons need the button to be
relativeand sized (w-11 h-11), or they collapse onto the baseline.
Browser support
| Chrome | Safari | Firefox | Edge |
|---|---|---|---|
| 111+ | 16.4+ | 128+ | 111+ |
The async Clipboard API is Baseline in secure contexts; color-mix() is v4's own floor.