12 / 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 Accent-Colour Toggle Breadcrumb with Persisted Theme
A trail whose accent is one custom property the user switches live from a swatch row — hover tint, current-page fill and every focus ring recolour from that single variable. Nine lines of JS persist the choice; the port adds aria-pressed so the selected swatch is announced, not just visible.
Untitled UI Pro: 5,000+ React + Tailwind CSS v4 components · from $349 one-time
Untitled UI React · Affiliate link
The code
<section class="tbc-12 w-full min-h-svh grid place-items-center gap-5 bg-tbc12-bg font-tbc12-sans px-6 py-8 [--tbc12-accent:oklch(0.6_0.18_265)]">
<div role="group" aria-label="Accent colour" class="flex items-center gap-2">
<button type="button" data-accent="oklch(0.6 0.18 265)" aria-pressed="true" aria-label="Indigo accent" style="background:oklch(0.6 0.18 265)" class="w-6.5 h-6.5 rounded-full border-2 border-white cursor-pointer ring-1 ring-tbc12-edge transition-[scale,box-shadow] duration-150 hover:scale-112 focus-visible:outline-2 focus-visible:outline-[var(--tbc12-accent)] focus-visible:outline-offset-3 aria-pressed:ring-2 aria-pressed:ring-tbc12-ink aria-pressed:ring-offset-2 motion-reduce:transition-none"></button>
<button type="button" data-accent="oklch(0.65 0.17 25)" aria-pressed="false" aria-label="Coral accent" style="background:oklch(0.65 0.17 25)" class="w-6.5 h-6.5 rounded-full border-2 border-white cursor-pointer ring-1 ring-tbc12-edge transition-[scale,box-shadow] duration-150 hover:scale-112 focus-visible:outline-2 focus-visible:outline-[var(--tbc12-accent)] focus-visible:outline-offset-3 aria-pressed:ring-2 aria-pressed:ring-tbc12-ink aria-pressed:ring-offset-2 motion-reduce:transition-none"></button>
<button type="button" data-accent="oklch(0.7 0.16 160)" aria-pressed="false" aria-label="Emerald accent" style="background:oklch(0.7 0.16 160)" class="w-6.5 h-6.5 rounded-full border-2 border-white cursor-pointer ring-1 ring-tbc12-edge transition-[scale,box-shadow] duration-150 hover:scale-112 focus-visible:outline-2 focus-visible:outline-[var(--tbc12-accent)] focus-visible:outline-offset-3 aria-pressed:ring-2 aria-pressed:ring-tbc12-ink aria-pressed:ring-offset-2 motion-reduce:transition-none"></button>
<button type="button" data-accent="oklch(0.72 0.15 60)" aria-pressed="false" aria-label="Amber accent" style="background:oklch(0.72 0.15 60)" class="w-6.5 h-6.5 rounded-full border-2 border-white cursor-pointer ring-1 ring-tbc12-edge transition-[scale,box-shadow] duration-150 hover:scale-112 focus-visible:outline-2 focus-visible:outline-[var(--tbc12-accent)] focus-visible:outline-offset-3 aria-pressed:ring-2 aria-pressed:ring-tbc12-ink aria-pressed:ring-offset-2 motion-reduce:transition-none"></button>
</div>
<nav aria-label="Breadcrumb">
<ol class="flex flex-wrap items-center list-none m-0 p-0">
<li class="flex items-center"><a href="#" class="flex items-center min-h-9 px-2.75 rounded-lg text-[13.5px] font-semibold text-tbc12-link no-underline transition-colors duration-200 hover:text-[var(--tbc12-accent)] hover:bg-[color-mix(in_oklab,var(--tbc12-accent)_12%,transparent)] focus-visible:outline-2 focus-visible:outline-[var(--tbc12-accent)] focus-visible:outline-offset-2 motion-reduce:transition-none">Home</a></li>
<li class="flex items-center before:content-['\203A'] before:mx-2 before:text-tbc12-sep"><a href="#" class="flex items-center min-h-9 px-2.75 rounded-lg text-[13.5px] font-semibold text-tbc12-link no-underline transition-colors duration-200 hover:text-[var(--tbc12-accent)] hover:bg-[color-mix(in_oklab,var(--tbc12-accent)_12%,transparent)] focus-visible:outline-2 focus-visible:outline-[var(--tbc12-accent)] focus-visible:outline-offset-2 motion-reduce:transition-none">Settings</a></li>
<li class="flex items-center before:content-['\203A'] before:mx-2 before:text-tbc12-sep"><a href="#" class="flex items-center min-h-9 px-2.75 rounded-lg text-[13.5px] font-semibold text-tbc12-link no-underline transition-colors duration-200 hover:text-[var(--tbc12-accent)] hover:bg-[color-mix(in_oklab,var(--tbc12-accent)_12%,transparent)] focus-visible:outline-2 focus-visible:outline-[var(--tbc12-accent)] focus-visible:outline-offset-2 motion-reduce:transition-none">Appearance</a></li>
<li class="flex items-center before:content-['\203A'] before:mx-2 before:text-tbc12-sep"><a href="#" aria-current="page" class="flex items-center min-h-9 px-2.75 rounded-lg text-[13.5px] font-bold text-white no-underline bg-[var(--tbc12-accent)] focus-visible:outline-2 focus-visible:outline-tbc12-ink focus-visible:outline-offset-2">Accent Colour</a></li>
</ol>
</nav>
</section><section class="tbc-12 w-full min-h-svh grid place-items-center gap-5 bg-tbc12-bg font-tbc12-sans px-6 py-8 [--tbc12-accent:oklch(0.6_0.18_265)]">
<div role="group" aria-label="Accent colour" class="flex items-center gap-2">
<button type="button" data-accent="oklch(0.6 0.18 265)" aria-pressed="true" aria-label="Indigo accent" style="background:oklch(0.6 0.18 265)" class="w-6.5 h-6.5 rounded-full border-2 border-white cursor-pointer ring-1 ring-tbc12-edge transition-[scale,box-shadow] duration-150 hover:scale-112 focus-visible:outline-2 focus-visible:outline-[var(--tbc12-accent)] focus-visible:outline-offset-3 aria-pressed:ring-2 aria-pressed:ring-tbc12-ink aria-pressed:ring-offset-2 motion-reduce:transition-none"></button>
<button type="button" data-accent="oklch(0.65 0.17 25)" aria-pressed="false" aria-label="Coral accent" style="background:oklch(0.65 0.17 25)" class="w-6.5 h-6.5 rounded-full border-2 border-white cursor-pointer ring-1 ring-tbc12-edge transition-[scale,box-shadow] duration-150 hover:scale-112 focus-visible:outline-2 focus-visible:outline-[var(--tbc12-accent)] focus-visible:outline-offset-3 aria-pressed:ring-2 aria-pressed:ring-tbc12-ink aria-pressed:ring-offset-2 motion-reduce:transition-none"></button>
<button type="button" data-accent="oklch(0.7 0.16 160)" aria-pressed="false" aria-label="Emerald accent" style="background:oklch(0.7 0.16 160)" class="w-6.5 h-6.5 rounded-full border-2 border-white cursor-pointer ring-1 ring-tbc12-edge transition-[scale,box-shadow] duration-150 hover:scale-112 focus-visible:outline-2 focus-visible:outline-[var(--tbc12-accent)] focus-visible:outline-offset-3 aria-pressed:ring-2 aria-pressed:ring-tbc12-ink aria-pressed:ring-offset-2 motion-reduce:transition-none"></button>
<button type="button" data-accent="oklch(0.72 0.15 60)" aria-pressed="false" aria-label="Amber accent" style="background:oklch(0.72 0.15 60)" class="w-6.5 h-6.5 rounded-full border-2 border-white cursor-pointer ring-1 ring-tbc12-edge transition-[scale,box-shadow] duration-150 hover:scale-112 focus-visible:outline-2 focus-visible:outline-[var(--tbc12-accent)] focus-visible:outline-offset-3 aria-pressed:ring-2 aria-pressed:ring-tbc12-ink aria-pressed:ring-offset-2 motion-reduce:transition-none"></button>
</div>
<nav aria-label="Breadcrumb">
<ol class="flex flex-wrap items-center list-none m-0 p-0">
<li class="flex items-center"><a href="#" class="flex items-center min-h-9 px-2.75 rounded-lg text-[13.5px] font-semibold text-tbc12-link no-underline transition-colors duration-200 hover:text-[var(--tbc12-accent)] hover:bg-[color-mix(in_oklab,var(--tbc12-accent)_12%,transparent)] focus-visible:outline-2 focus-visible:outline-[var(--tbc12-accent)] focus-visible:outline-offset-2 motion-reduce:transition-none">Home</a></li>
<li class="flex items-center before:content-['\203A'] before:mx-2 before:text-tbc12-sep"><a href="#" class="flex items-center min-h-9 px-2.75 rounded-lg text-[13.5px] font-semibold text-tbc12-link no-underline transition-colors duration-200 hover:text-[var(--tbc12-accent)] hover:bg-[color-mix(in_oklab,var(--tbc12-accent)_12%,transparent)] focus-visible:outline-2 focus-visible:outline-[var(--tbc12-accent)] focus-visible:outline-offset-2 motion-reduce:transition-none">Settings</a></li>
<li class="flex items-center before:content-['\203A'] before:mx-2 before:text-tbc12-sep"><a href="#" class="flex items-center min-h-9 px-2.75 rounded-lg text-[13.5px] font-semibold text-tbc12-link no-underline transition-colors duration-200 hover:text-[var(--tbc12-accent)] hover:bg-[color-mix(in_oklab,var(--tbc12-accent)_12%,transparent)] focus-visible:outline-2 focus-visible:outline-[var(--tbc12-accent)] focus-visible:outline-offset-2 motion-reduce:transition-none">Appearance</a></li>
<li class="flex items-center before:content-['\203A'] before:mx-2 before:text-tbc12-sep"><a href="#" aria-current="page" class="flex items-center min-h-9 px-2.75 rounded-lg text-[13.5px] font-bold text-white no-underline bg-[var(--tbc12-accent)] focus-visible:outline-2 focus-visible:outline-tbc12-ink focus-visible:outline-offset-2">Accent Colour</a></li>
</ol>
</nav>
</section>@import "tailwindcss";
@theme {
--color-tbc12-bg: #fbfbfd;
--color-tbc12-bg: oklch(0.98 0.004 265);
--color-tbc12-edge: #d9dae2;
--color-tbc12-edge: oklch(0.86 0.01 265);
--color-tbc12-link: #63666f;
--color-tbc12-link: oklch(0.45 0.03 265);
--color-tbc12-sep: #adb0ba;
--color-tbc12-sep: oklch(0.72 0.02 265);
--color-tbc12-ink: #2f323a;
--color-tbc12-ink: oklch(0.26 0.02 265);
--font-tbc12-sans: 'Space Grotesk', system-ui, sans-serif;
}
.tbc-12 {
width: 100%;
min-height: 100svh;
}@import "tailwindcss";
@theme {
--color-tbc12-bg: #fbfbfd;
--color-tbc12-bg: oklch(0.98 0.004 265);
--color-tbc12-edge: #d9dae2;
--color-tbc12-edge: oklch(0.86 0.01 265);
--color-tbc12-link: #63666f;
--color-tbc12-link: oklch(0.45 0.03 265);
--color-tbc12-sep: #adb0ba;
--color-tbc12-sep: oklch(0.72 0.02 265);
--color-tbc12-ink: #2f323a;
--color-tbc12-ink: oklch(0.26 0.02 265);
--font-tbc12-sans: 'Space Grotesk', system-ui, sans-serif;
}
.tbc-12 {
width: 100%;
min-height: 100svh;
}(function () {
document.querySelectorAll('.tbc-12').forEach(function (root) {
if (root.dataset.bound) return; root.dataset.bound = '1';
var KEY = 'tbc12-accent', swatches = root.querySelectorAll('button[data-accent]');
function apply(c) {
root.style.setProperty('--tbc12-accent', c);
swatches.forEach(function (b) { b.setAttribute('aria-pressed', String(b.dataset.accent === c)); });
}
try { var saved = localStorage.getItem(KEY); if (saved) apply(saved); } catch (e) {}
swatches.forEach(function (btn) {
btn.addEventListener('click', function () {
apply(btn.dataset.accent);
try { localStorage.setItem(KEY, btn.dataset.accent); } catch (e) {}
});
});
});
})();(function () {
document.querySelectorAll('.tbc-12').forEach(function (root) {
if (root.dataset.bound) return; root.dataset.bound = '1';
var KEY = 'tbc12-accent', swatches = root.querySelectorAll('button[data-accent]');
function apply(c) {
root.style.setProperty('--tbc12-accent', c);
swatches.forEach(function (b) { b.setAttribute('aria-pressed', String(b.dataset.accent === c)); });
}
try { var saved = localStorage.getItem(KEY); if (saved) apply(saved); } catch (e) {}
swatches.forEach(function (btn) {
btn.addEventListener('click', function () {
apply(btn.dataset.accent);
try { localStorage.setItem(KEY, btn.dataset.accent); } catch (e) {}
});
});
});
})();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-tbc12-bg: #fbfbfd;
--color-tbc12-bg: oklch(0.98 0.004 265);
--color-tbc12-edge: #d9dae2;
--color-tbc12-edge: oklch(0.86 0.01 265);
--color-tbc12-link: #63666f;
--color-tbc12-link: oklch(0.45 0.03 265);
--color-tbc12-sep: #adb0ba;
--color-tbc12-sep: oklch(0.72 0.02 265);
--color-tbc12-ink: #2f323a;
--color-tbc12-ink: oklch(0.26 0.02 265);
--font-tbc12-sans: 'Space Grotesk', system-ui, sans-serif;
}
.tbc-12 {
width: 100%;
min-height: 100svh;
}@import "tailwindcss";
@theme {
--color-tbc12-bg: #fbfbfd;
--color-tbc12-bg: oklch(0.98 0.004 265);
--color-tbc12-edge: #d9dae2;
--color-tbc12-edge: oklch(0.86 0.01 265);
--color-tbc12-link: #63666f;
--color-tbc12-link: oklch(0.45 0.03 265);
--color-tbc12-sep: #adb0ba;
--color-tbc12-sep: oklch(0.72 0.02 265);
--color-tbc12-ink: #2f323a;
--color-tbc12-ink: oklch(0.26 0.02 265);
--font-tbc12-sans: 'Space Grotesk', system-ui, sans-serif;
}
.tbc-12 {
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=Space+Grotesk:wght@400;500;600;700&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=Space+Grotesk:wght@400;500;600;700&display=swap">What changed in the port
Which parts became utilities, which stayed CSS, and why.
- Live theming is the case where arbitrary utilities reading a
var()are strictly better than tokens:bg-[var(--tbc12-accent)]compiles once and re-resolves forever, while a@themecolour would need a rebuild to change. - UI change from the CSS original: the swatches gained
aria-pressedand anaria-pressed:ring-2selection ring. The original showed no selected state at all — you could not tell which accent was active without comparing it to the trail. - The script grew from nine lines to fifteen only because it now keeps
aria-pressedhonest across the row. It still touches exactly one custom property and one attribute.
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 Accent-Colour Toggle Breadcrumb with Persisted Theme
Source: https://codefronts.com/navigation/tailwind-css-breadcrumbs/tailwind-accent-colour-toggle-breadcrumb-persisted-theme/
A trail whose accent is one custom property the user switches live from a swatch row — hover tint, current-page fill and every focus ring recolour from that single variable. Nine lines of JS persist the choice; the port adds aria-pressed so the selected swatch is announced, not just visible.
## HTML
```html
<section class="tbc-12 w-full min-h-svh grid place-items-center gap-5 bg-tbc12-bg font-tbc12-sans px-6 py-8 [--tbc12-accent:oklch(0.6_0.18_265)]">
<div role="group" aria-label="Accent colour" class="flex items-center gap-2">
<button type="button" data-accent="oklch(0.6 0.18 265)" aria-pressed="true" aria-label="Indigo accent" style="background:oklch(0.6 0.18 265)" class="w-6.5 h-6.5 rounded-full border-2 border-white cursor-pointer ring-1 ring-tbc12-edge transition-[scale,box-shadow] duration-150 hover:scale-112 focus-visible:outline-2 focus-visible:outline-[var(--tbc12-accent)] focus-visible:outline-offset-3 aria-pressed:ring-2 aria-pressed:ring-tbc12-ink aria-pressed:ring-offset-2 motion-reduce:transition-none"></button>
<button type="button" data-accent="oklch(0.65 0.17 25)" aria-pressed="false" aria-label="Coral accent" style="background:oklch(0.65 0.17 25)" class="w-6.5 h-6.5 rounded-full border-2 border-white cursor-pointer ring-1 ring-tbc12-edge transition-[scale,box-shadow] duration-150 hover:scale-112 focus-visible:outline-2 focus-visible:outline-[var(--tbc12-accent)] focus-visible:outline-offset-3 aria-pressed:ring-2 aria-pressed:ring-tbc12-ink aria-pressed:ring-offset-2 motion-reduce:transition-none"></button>
<button type="button" data-accent="oklch(0.7 0.16 160)" aria-pressed="false" aria-label="Emerald accent" style="background:oklch(0.7 0.16 160)" class="w-6.5 h-6.5 rounded-full border-2 border-white cursor-pointer ring-1 ring-tbc12-edge transition-[scale,box-shadow] duration-150 hover:scale-112 focus-visible:outline-2 focus-visible:outline-[var(--tbc12-accent)] focus-visible:outline-offset-3 aria-pressed:ring-2 aria-pressed:ring-tbc12-ink aria-pressed:ring-offset-2 motion-reduce:transition-none"></button>
<button type="button" data-accent="oklch(0.72 0.15 60)" aria-pressed="false" aria-label="Amber accent" style="background:oklch(0.72 0.15 60)" class="w-6.5 h-6.5 rounded-full border-2 border-white cursor-pointer ring-1 ring-tbc12-edge transition-[scale,box-shadow] duration-150 hover:scale-112 focus-visible:outline-2 focus-visible:outline-[var(--tbc12-accent)] focus-visible:outline-offset-3 aria-pressed:ring-2 aria-pressed:ring-tbc12-ink aria-pressed:ring-offset-2 motion-reduce:transition-none"></button>
</div>
<nav aria-label="Breadcrumb">
<ol class="flex flex-wrap items-center list-none m-0 p-0">
<li class="flex items-center"><a href="#" class="flex items-center min-h-9 px-2.75 rounded-lg text-[13.5px] font-semibold text-tbc12-link no-underline transition-colors duration-200 hover:text-[var(--tbc12-accent)] hover:bg-[color-mix(in_oklab,var(--tbc12-accent)_12%,transparent)] focus-visible:outline-2 focus-visible:outline-[var(--tbc12-accent)] focus-visible:outline-offset-2 motion-reduce:transition-none">Home</a></li>
<li class="flex items-center before:content-['\203A'] before:mx-2 before:text-tbc12-sep"><a href="#" class="flex items-center min-h-9 px-2.75 rounded-lg text-[13.5px] font-semibold text-tbc12-link no-underline transition-colors duration-200 hover:text-[var(--tbc12-accent)] hover:bg-[color-mix(in_oklab,var(--tbc12-accent)_12%,transparent)] focus-visible:outline-2 focus-visible:outline-[var(--tbc12-accent)] focus-visible:outline-offset-2 motion-reduce:transition-none">Settings</a></li>
<li class="flex items-center before:content-['\203A'] before:mx-2 before:text-tbc12-sep"><a href="#" class="flex items-center min-h-9 px-2.75 rounded-lg text-[13.5px] font-semibold text-tbc12-link no-underline transition-colors duration-200 hover:text-[var(--tbc12-accent)] hover:bg-[color-mix(in_oklab,var(--tbc12-accent)_12%,transparent)] focus-visible:outline-2 focus-visible:outline-[var(--tbc12-accent)] focus-visible:outline-offset-2 motion-reduce:transition-none">Appearance</a></li>
<li class="flex items-center before:content-['\203A'] before:mx-2 before:text-tbc12-sep"><a href="#" aria-current="page" class="flex items-center min-h-9 px-2.75 rounded-lg text-[13.5px] font-bold text-white no-underline bg-[var(--tbc12-accent)] focus-visible:outline-2 focus-visible:outline-tbc12-ink focus-visible:outline-offset-2">Accent Colour</a></li>
</ol>
</nav>
</section>
```
## CSS
```css
@import "tailwindcss";
@theme {
--color-tbc12-bg: #fbfbfd;
--color-tbc12-bg: oklch(0.98 0.004 265);
--color-tbc12-edge: #d9dae2;
--color-tbc12-edge: oklch(0.86 0.01 265);
--color-tbc12-link: #63666f;
--color-tbc12-link: oklch(0.45 0.03 265);
--color-tbc12-sep: #adb0ba;
--color-tbc12-sep: oklch(0.72 0.02 265);
--color-tbc12-ink: #2f323a;
--color-tbc12-ink: oklch(0.26 0.02 265);
--font-tbc12-sans: 'Space Grotesk', system-ui, sans-serif;
}
.tbc-12 {
width: 100%;
min-height: 100svh;
}
```
## JavaScript
```js
(function () {
document.querySelectorAll('.tbc-12').forEach(function (root) {
if (root.dataset.bound) return; root.dataset.bound = '1';
var KEY = 'tbc12-accent', swatches = root.querySelectorAll('button[data-accent]');
function apply(c) {
root.style.setProperty('--tbc12-accent', c);
swatches.forEach(function (b) { b.setAttribute('aria-pressed', String(b.dataset.accent === c)); });
}
try { var saved = localStorage.getItem(KEY); if (saved) apply(saved); } catch (e) {}
swatches.forEach(function (btn) {
btn.addEventListener('click', function () {
apply(btn.dataset.accent);
try { localStorage.setItem(KEY, btn.dataset.accent); } catch (e) {}
});
});
});
})();
```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 Accent-Colour Toggle Breadcrumb with Persisted Theme
Source: https://codefronts.com/navigation/tailwind-css-breadcrumbs/tailwind-accent-colour-toggle-breadcrumb-persisted-theme/
A trail whose accent is one custom property the user switches live from a swatch row — hover tint, current-page fill and every focus ring recolour from that single variable. Nine lines of JS persist the choice; the port adds aria-pressed so the selected swatch is announced, not just visible.
## HTML
```html
<section class="tbc-12 w-full min-h-svh grid place-items-center gap-5 bg-tbc12-bg font-tbc12-sans px-6 py-8 [--tbc12-accent:oklch(0.6_0.18_265)]">
<div role="group" aria-label="Accent colour" class="flex items-center gap-2">
<button type="button" data-accent="oklch(0.6 0.18 265)" aria-pressed="true" aria-label="Indigo accent" style="background:oklch(0.6 0.18 265)" class="w-6.5 h-6.5 rounded-full border-2 border-white cursor-pointer ring-1 ring-tbc12-edge transition-[scale,box-shadow] duration-150 hover:scale-112 focus-visible:outline-2 focus-visible:outline-[var(--tbc12-accent)] focus-visible:outline-offset-3 aria-pressed:ring-2 aria-pressed:ring-tbc12-ink aria-pressed:ring-offset-2 motion-reduce:transition-none"></button>
<button type="button" data-accent="oklch(0.65 0.17 25)" aria-pressed="false" aria-label="Coral accent" style="background:oklch(0.65 0.17 25)" class="w-6.5 h-6.5 rounded-full border-2 border-white cursor-pointer ring-1 ring-tbc12-edge transition-[scale,box-shadow] duration-150 hover:scale-112 focus-visible:outline-2 focus-visible:outline-[var(--tbc12-accent)] focus-visible:outline-offset-3 aria-pressed:ring-2 aria-pressed:ring-tbc12-ink aria-pressed:ring-offset-2 motion-reduce:transition-none"></button>
<button type="button" data-accent="oklch(0.7 0.16 160)" aria-pressed="false" aria-label="Emerald accent" style="background:oklch(0.7 0.16 160)" class="w-6.5 h-6.5 rounded-full border-2 border-white cursor-pointer ring-1 ring-tbc12-edge transition-[scale,box-shadow] duration-150 hover:scale-112 focus-visible:outline-2 focus-visible:outline-[var(--tbc12-accent)] focus-visible:outline-offset-3 aria-pressed:ring-2 aria-pressed:ring-tbc12-ink aria-pressed:ring-offset-2 motion-reduce:transition-none"></button>
<button type="button" data-accent="oklch(0.72 0.15 60)" aria-pressed="false" aria-label="Amber accent" style="background:oklch(0.72 0.15 60)" class="w-6.5 h-6.5 rounded-full border-2 border-white cursor-pointer ring-1 ring-tbc12-edge transition-[scale,box-shadow] duration-150 hover:scale-112 focus-visible:outline-2 focus-visible:outline-[var(--tbc12-accent)] focus-visible:outline-offset-3 aria-pressed:ring-2 aria-pressed:ring-tbc12-ink aria-pressed:ring-offset-2 motion-reduce:transition-none"></button>
</div>
<nav aria-label="Breadcrumb">
<ol class="flex flex-wrap items-center list-none m-0 p-0">
<li class="flex items-center"><a href="#" class="flex items-center min-h-9 px-2.75 rounded-lg text-[13.5px] font-semibold text-tbc12-link no-underline transition-colors duration-200 hover:text-[var(--tbc12-accent)] hover:bg-[color-mix(in_oklab,var(--tbc12-accent)_12%,transparent)] focus-visible:outline-2 focus-visible:outline-[var(--tbc12-accent)] focus-visible:outline-offset-2 motion-reduce:transition-none">Home</a></li>
<li class="flex items-center before:content-['\203A'] before:mx-2 before:text-tbc12-sep"><a href="#" class="flex items-center min-h-9 px-2.75 rounded-lg text-[13.5px] font-semibold text-tbc12-link no-underline transition-colors duration-200 hover:text-[var(--tbc12-accent)] hover:bg-[color-mix(in_oklab,var(--tbc12-accent)_12%,transparent)] focus-visible:outline-2 focus-visible:outline-[var(--tbc12-accent)] focus-visible:outline-offset-2 motion-reduce:transition-none">Settings</a></li>
<li class="flex items-center before:content-['\203A'] before:mx-2 before:text-tbc12-sep"><a href="#" class="flex items-center min-h-9 px-2.75 rounded-lg text-[13.5px] font-semibold text-tbc12-link no-underline transition-colors duration-200 hover:text-[var(--tbc12-accent)] hover:bg-[color-mix(in_oklab,var(--tbc12-accent)_12%,transparent)] focus-visible:outline-2 focus-visible:outline-[var(--tbc12-accent)] focus-visible:outline-offset-2 motion-reduce:transition-none">Appearance</a></li>
<li class="flex items-center before:content-['\203A'] before:mx-2 before:text-tbc12-sep"><a href="#" aria-current="page" class="flex items-center min-h-9 px-2.75 rounded-lg text-[13.5px] font-bold text-white no-underline bg-[var(--tbc12-accent)] focus-visible:outline-2 focus-visible:outline-tbc12-ink focus-visible:outline-offset-2">Accent Colour</a></li>
</ol>
</nav>
</section>
```
## CSS
```css
@import "tailwindcss";
@theme {
--color-tbc12-bg: #fbfbfd;
--color-tbc12-bg: oklch(0.98 0.004 265);
--color-tbc12-edge: #d9dae2;
--color-tbc12-edge: oklch(0.86 0.01 265);
--color-tbc12-link: #63666f;
--color-tbc12-link: oklch(0.45 0.03 265);
--color-tbc12-sep: #adb0ba;
--color-tbc12-sep: oklch(0.72 0.02 265);
--color-tbc12-ink: #2f323a;
--color-tbc12-ink: oklch(0.26 0.02 265);
--font-tbc12-sans: 'Space Grotesk', system-ui, sans-serif;
}
.tbc-12 {
width: 100%;
min-height: 100svh;
}
```
## JavaScript
```js
(function () {
document.querySelectorAll('.tbc-12').forEach(function (root) {
if (root.dataset.bound) return; root.dataset.bound = '1';
var KEY = 'tbc12-accent', swatches = root.querySelectorAll('button[data-accent]');
function apply(c) {
root.style.setProperty('--tbc12-accent', c);
swatches.forEach(function (b) { b.setAttribute('aria-pressed', String(b.dataset.accent === c)); });
}
try { var saved = localStorage.getItem(KEY); if (saved) apply(saved); } catch (e) {}
swatches.forEach(function (btn) {
btn.addEventListener('click', function () {
apply(btn.dataset.accent);
try { localStorage.setItem(KEY, btn.dataset.accent); } catch (e) {}
});
});
});
})();
```How this works
The variable is the theme. --tbc12-accent lives on the component root; the crumbs reference it through arbitrary utilities. Tailwind compiles those once, and the browser re-resolves them whenever the variable changes — which is why live theming needs no rebuild and no dark:-style variant.
class="hover:text-[var(--tbc12-accent)]
hover:bg-[color-mix(in_oklab,var(--tbc12-accent)_12%,transparent)]"The swatch row is a toolbar of toggle buttons. Each carries aria-pressed, so the selected accent is programmatically determinable, and aria-pressed:ring-2 gives it a visible ring rather than relying on the fill alone. The CSS original left the selection invisible — a small bug that only an accessibility pass catches.
Persistence is the only reason for script. Read localStorage on load, write it on click, guard both in try/catch for private-mode Safari.
Make it yours
- Palette: the
data-accentvalues on the buttons. Four is a curated set; a free colour picker would defeat the point. - Tint strength: the
12%in thecolor-mix(). - Scope the theme wider by moving
--tbc12-accentto:root— every utility that reads it follows.
Gotchas — read before shipping
- A swatch must not rely on colour alone to show selection — hence
aria-pressedplus a ring. WCAG 1.4.1. localStoragethrows in some privacy modes; both accesses are wrapped.- Arbitrary utilities reading a variable are compiled as written, so the variable must exist at runtime. A typo in the property name fails silently to the inherited value.
Browser support
| Chrome | Safari | Firefox | Edge |
|---|---|---|---|
| 111+ | 16.4+ | 128+ | 111+ |
color-mix() is the gate and is Tailwind v4's own floor; custom-property theming works far further back.