13 / 30
All 30 in 30 Tailwind CSS Sidebar Layouts
- 01Tailwind SaaS Dashboard Sidebar with Native Dark Mode Switch
- 02Tailwind Collapsible Admin Sidebar with Icon Tooltips
- 03Tailwind Documentation Sidebar with Multi-Level :target Tree
- 04Tailwind Responsive Sidebar to Bottom Navigation Switch Layout
- 05Tailwind Analytics Sidebar with CSS Subgrid Column Alignment
- 06Tailwind Animated Collapsible Sidebar with Icon-Only Mode
- 07Tailwind Sticky Sidebar Layout with Scroll-Driven Progress Bar
- 08Tailwind Pure CSS Collapsible Sidebar Drawer without JavaScript
- 09Tailwind Fixed Sidebar Layout with Independently Scrolling Content
- 10Tailwind Off-Canvas Navigation Drawer with the Popover API
- 11Tailwind Right-Aligned Sidebar Layout for Inspector Panels
- 12Tailwind Two-Pane Webmail Layout with List and Reading Pane
- 13Tailwind Dual Sidebar App Shell with Left Nav and Context Panel
- 14Tailwind Mini Icon Rail Sidebar with Anchor-Positioned Active Pill
- 15Tailwind E-Commerce Filter Sidebar with Native Details Accordion
- 16Tailwind Floating Glassmorphism Sidebar with Gradient Hairline
- 17Tailwind Sidebar Menu with Pinned User Profile Footer
- 18Tailwind Push-Content Sidebar Drawer with GPU Transitions
- 19Tailwind Off-Canvas Cart Overlay with Blurred Backdrop Scrim
- 20Tailwind Sidebar with Persistent Collapsed State in localStorage
- 21Tailwind Sidebar with Sticky Search Bar Inside the Rail
- 22Tailwind Section-Grouped Sidebar Navigation with Header Labels
- 23Tailwind Sliding Active Indicator Sidebar with CSS :target
- 24Tailwind Multi-Level Nested Tree Sidebar with Details Branches
- 25Tailwind Tabbed Sidebar with Radio-Driven Panel Switching
- 26Tailwind Onboarding Wizard Sidebar with Step Progress Tracking
- 27Tailwind Resizable Sidebar Layout Using the CSS Resize Property
- 28Tailwind Three-Pane Workspace Shell with Icon Rail and List
- 29Tailwind Adaptive Sidebar Layout Using CSS Container Queries
- 30Tailwind Frosted Glass Floating Sidebar with Animated Aurora
Tailwind Dual Sidebar App Shell with Left Nav and Context Panel
The Notion/Discord-class shell: primary nav left, contextual panel right, content between. The most valuable line in the demo is minmax(0,1fr) on the middle track — the answer to the most-asked grid question on the internet, and one that reads more clearly as a utility than as CSS.
Mosaic by Cruip: a complete Tailwind admin dashboard template in HTML, React, Next.js and Vue · $69
Cruip · Mosaic by Cruip · Affiliate link
The code
<section class="tsl-13 w-full h-svh min-h-svh grid grid-cols-[232px_minmax(0,1fr)_280px] max-xl:grid-cols-[232px_minmax(0,1fr)] font-tsl13-sans bg-tsl13-bg text-tsl13-ink">
<aside aria-label="Workspace" class="bg-tsl13-panel border-r border-tsl13-line px-2.5 py-4 overflow-y-auto">
<div class="flex items-center gap-2.5 px-2.5 pt-0.5 pb-4 text-[14.5px] font-bold tracking-tight"><span aria-hidden="true" class="grid place-items-center w-[26px] h-[26px] rounded-lg text-xs font-bold text-white bg-[linear-gradient(135deg,var(--color-tsl13-accent),oklch(0.6_0.18_260))]">L</span>Loomcraft</div>
<div class="px-2.5 pt-3.5 pb-1.5 text-[10.5px] font-semibold uppercase tracking-[0.09em] text-tsl13-mut">Projects</div>
<nav class="flex flex-col gap-px">
<a href="#" aria-current="page" class="flex items-center min-h-11 px-3 rounded-lg text-[13.5px] font-medium text-tsl13-mut no-underline transition-colors duration-150 hover:text-tsl13-ink hover:bg-tsl13-hover aria-[current=page]:text-tsl13-ink aria-[current=page]:bg-tsl13-tint focus-visible:outline-2 focus-visible:outline-tsl13-accent focus-visible:outline-offset-1"># brand-refresh <span class="ml-auto rounded-full px-[7px] py-[3px] text-[10.5px] font-bold text-white bg-tsl13-accent">3</span></a>
<a href="#" class="flex items-center min-h-11 px-3 rounded-lg text-[13.5px] font-medium text-tsl13-mut no-underline transition-colors duration-150 hover:text-tsl13-ink hover:bg-tsl13-hover focus-visible:outline-2 focus-visible:outline-tsl13-accent focus-visible:outline-offset-1"># website-v4</a>
<a href="#" class="flex items-center min-h-11 px-3 rounded-lg text-[13.5px] font-medium text-tsl13-mut no-underline transition-colors duration-150 hover:text-tsl13-ink hover:bg-tsl13-hover focus-visible:outline-2 focus-visible:outline-tsl13-accent focus-visible:outline-offset-1"># mobile-app <span class="ml-auto rounded-full px-[7px] py-[3px] text-[10.5px] font-bold text-white bg-tsl13-accent">12</span></a>
</nav>
<div class="px-2.5 pt-3.5 pb-1.5 text-[10.5px] font-semibold uppercase tracking-[0.09em] text-tsl13-mut">Team</div>
<nav class="flex flex-col gap-px">
<a href="#" class="flex items-center min-h-11 px-3 rounded-lg text-[13.5px] font-medium text-tsl13-mut no-underline transition-colors duration-150 hover:text-tsl13-ink hover:bg-tsl13-hover focus-visible:outline-2 focus-visible:outline-tsl13-accent focus-visible:outline-offset-1"># design-crit</a>
<a href="#" class="flex items-center min-h-11 px-3 rounded-lg text-[13.5px] font-medium text-tsl13-mut no-underline transition-colors duration-150 hover:text-tsl13-ink hover:bg-tsl13-hover focus-visible:outline-2 focus-visible:outline-tsl13-accent focus-visible:outline-offset-1"># announcements</a>
</nav>
</aside>
<main class="overflow-y-auto px-[34px] py-[30px] [scrollbar-gutter:stable]">
<h1 class="mb-3 text-xl font-bold leading-tight"># brand-refresh</h1>
<p class="max-w-[60ch] text-sm leading-[1.7] text-tsl13-mut text-pretty">The centre track is <code class="font-tsl13-mono text-[12.5px] px-1.5 py-0.5 rounded-[5px] bg-tsl13-hover text-tsl13-ink">minmax(0,1fr)</code> — wide content shrinks and scrolls instead of crushing the context panel. Narrow the window past 1280px: the right panel yields first, the nav survives.</p>
</main>
<aside aria-label="Activity" class="max-xl:hidden border-l border-tsl13-line bg-tsl13-panel px-4 py-5 overflow-y-auto">
<h2 class="mb-4 text-xs font-semibold uppercase tracking-[0.08em] text-tsl13-mut">Activity</h2>
<ol class="list-none m-0 p-0 grid">
<li class="relative grid grid-cols-[28px_1fr] gap-3 pb-5 before:content-[''] before:absolute before:left-[13.5px] before:top-8 before:bottom-0.5 before:w-px before:bg-tsl13-line last:before:hidden"><span aria-hidden="true" class="grid place-items-center w-7 h-7 rounded-full text-[9.5px] font-bold text-white bg-[linear-gradient(135deg,oklch(0.6_0.15_300),oklch(0.55_0.15_240))]">PR</span><div class="text-[12.5px] leading-[1.5] text-tsl13-mut"><strong class="font-semibold text-tsl13-ink">Priya</strong> shipped the new wordmark<time class="block mt-0.5 text-[11px] text-tsl13-faint">2h ago</time></div></li>
<li class="relative grid grid-cols-[28px_1fr] gap-3 pb-5 before:content-[''] before:absolute before:left-[13.5px] before:top-8 before:bottom-0.5 before:w-px before:bg-tsl13-line last:before:hidden"><span aria-hidden="true" class="grid place-items-center w-7 h-7 rounded-full text-[9.5px] font-bold text-white bg-[linear-gradient(135deg,oklch(0.6_0.15_300),oklch(0.55_0.15_240))]">MW</span><div class="text-[12.5px] leading-[1.5] text-tsl13-mut"><strong class="font-semibold text-tsl13-ink">Marcus</strong> commented on palette v3<time class="block mt-0.5 text-[11px] text-tsl13-faint">4h ago</time></div></li>
<li class="relative grid grid-cols-[28px_1fr] gap-3 pb-5 before:content-[''] before:absolute before:left-[13.5px] before:top-8 before:bottom-0.5 before:w-px before:bg-tsl13-line last:before:hidden"><span aria-hidden="true" class="grid place-items-center w-7 h-7 rounded-full text-[9.5px] font-bold text-white bg-[linear-gradient(135deg,oklch(0.6_0.15_300),oklch(0.55_0.15_240))]">AO</span><div class="text-[12.5px] leading-[1.5] text-tsl13-mut"><strong class="font-semibold text-tsl13-ink">Amara</strong> uploaded 6 explorations<time class="block mt-0.5 text-[11px] text-tsl13-faint">Yesterday</time></div></li>
</ol>
</aside>
</section><section class="tsl-13 w-full h-svh min-h-svh grid grid-cols-[232px_minmax(0,1fr)_280px] max-xl:grid-cols-[232px_minmax(0,1fr)] font-tsl13-sans bg-tsl13-bg text-tsl13-ink">
<aside aria-label="Workspace" class="bg-tsl13-panel border-r border-tsl13-line px-2.5 py-4 overflow-y-auto">
<div class="flex items-center gap-2.5 px-2.5 pt-0.5 pb-4 text-[14.5px] font-bold tracking-tight"><span aria-hidden="true" class="grid place-items-center w-[26px] h-[26px] rounded-lg text-xs font-bold text-white bg-[linear-gradient(135deg,var(--color-tsl13-accent),oklch(0.6_0.18_260))]">L</span>Loomcraft</div>
<div class="px-2.5 pt-3.5 pb-1.5 text-[10.5px] font-semibold uppercase tracking-[0.09em] text-tsl13-mut">Projects</div>
<nav class="flex flex-col gap-px">
<a href="#" aria-current="page" class="flex items-center min-h-11 px-3 rounded-lg text-[13.5px] font-medium text-tsl13-mut no-underline transition-colors duration-150 hover:text-tsl13-ink hover:bg-tsl13-hover aria-[current=page]:text-tsl13-ink aria-[current=page]:bg-tsl13-tint focus-visible:outline-2 focus-visible:outline-tsl13-accent focus-visible:outline-offset-1"># brand-refresh <span class="ml-auto rounded-full px-[7px] py-[3px] text-[10.5px] font-bold text-white bg-tsl13-accent">3</span></a>
<a href="#" class="flex items-center min-h-11 px-3 rounded-lg text-[13.5px] font-medium text-tsl13-mut no-underline transition-colors duration-150 hover:text-tsl13-ink hover:bg-tsl13-hover focus-visible:outline-2 focus-visible:outline-tsl13-accent focus-visible:outline-offset-1"># website-v4</a>
<a href="#" class="flex items-center min-h-11 px-3 rounded-lg text-[13.5px] font-medium text-tsl13-mut no-underline transition-colors duration-150 hover:text-tsl13-ink hover:bg-tsl13-hover focus-visible:outline-2 focus-visible:outline-tsl13-accent focus-visible:outline-offset-1"># mobile-app <span class="ml-auto rounded-full px-[7px] py-[3px] text-[10.5px] font-bold text-white bg-tsl13-accent">12</span></a>
</nav>
<div class="px-2.5 pt-3.5 pb-1.5 text-[10.5px] font-semibold uppercase tracking-[0.09em] text-tsl13-mut">Team</div>
<nav class="flex flex-col gap-px">
<a href="#" class="flex items-center min-h-11 px-3 rounded-lg text-[13.5px] font-medium text-tsl13-mut no-underline transition-colors duration-150 hover:text-tsl13-ink hover:bg-tsl13-hover focus-visible:outline-2 focus-visible:outline-tsl13-accent focus-visible:outline-offset-1"># design-crit</a>
<a href="#" class="flex items-center min-h-11 px-3 rounded-lg text-[13.5px] font-medium text-tsl13-mut no-underline transition-colors duration-150 hover:text-tsl13-ink hover:bg-tsl13-hover focus-visible:outline-2 focus-visible:outline-tsl13-accent focus-visible:outline-offset-1"># announcements</a>
</nav>
</aside>
<main class="overflow-y-auto px-[34px] py-[30px] [scrollbar-gutter:stable]">
<h1 class="mb-3 text-xl font-bold leading-tight"># brand-refresh</h1>
<p class="max-w-[60ch] text-sm leading-[1.7] text-tsl13-mut text-pretty">The centre track is <code class="font-tsl13-mono text-[12.5px] px-1.5 py-0.5 rounded-[5px] bg-tsl13-hover text-tsl13-ink">minmax(0,1fr)</code> — wide content shrinks and scrolls instead of crushing the context panel. Narrow the window past 1280px: the right panel yields first, the nav survives.</p>
</main>
<aside aria-label="Activity" class="max-xl:hidden border-l border-tsl13-line bg-tsl13-panel px-4 py-5 overflow-y-auto">
<h2 class="mb-4 text-xs font-semibold uppercase tracking-[0.08em] text-tsl13-mut">Activity</h2>
<ol class="list-none m-0 p-0 grid">
<li class="relative grid grid-cols-[28px_1fr] gap-3 pb-5 before:content-[''] before:absolute before:left-[13.5px] before:top-8 before:bottom-0.5 before:w-px before:bg-tsl13-line last:before:hidden"><span aria-hidden="true" class="grid place-items-center w-7 h-7 rounded-full text-[9.5px] font-bold text-white bg-[linear-gradient(135deg,oklch(0.6_0.15_300),oklch(0.55_0.15_240))]">PR</span><div class="text-[12.5px] leading-[1.5] text-tsl13-mut"><strong class="font-semibold text-tsl13-ink">Priya</strong> shipped the new wordmark<time class="block mt-0.5 text-[11px] text-tsl13-faint">2h ago</time></div></li>
<li class="relative grid grid-cols-[28px_1fr] gap-3 pb-5 before:content-[''] before:absolute before:left-[13.5px] before:top-8 before:bottom-0.5 before:w-px before:bg-tsl13-line last:before:hidden"><span aria-hidden="true" class="grid place-items-center w-7 h-7 rounded-full text-[9.5px] font-bold text-white bg-[linear-gradient(135deg,oklch(0.6_0.15_300),oklch(0.55_0.15_240))]">MW</span><div class="text-[12.5px] leading-[1.5] text-tsl13-mut"><strong class="font-semibold text-tsl13-ink">Marcus</strong> commented on palette v3<time class="block mt-0.5 text-[11px] text-tsl13-faint">4h ago</time></div></li>
<li class="relative grid grid-cols-[28px_1fr] gap-3 pb-5 before:content-[''] before:absolute before:left-[13.5px] before:top-8 before:bottom-0.5 before:w-px before:bg-tsl13-line last:before:hidden"><span aria-hidden="true" class="grid place-items-center w-7 h-7 rounded-full text-[9.5px] font-bold text-white bg-[linear-gradient(135deg,oklch(0.6_0.15_300),oklch(0.55_0.15_240))]">AO</span><div class="text-[12.5px] leading-[1.5] text-tsl13-mut"><strong class="font-semibold text-tsl13-ink">Amara</strong> uploaded 6 explorations<time class="block mt-0.5 text-[11px] text-tsl13-faint">Yesterday</time></div></li>
</ol>
</aside>
</section>@import "tailwindcss";
@theme {
--color-tsl13-bg: #16141c;
--color-tsl13-bg: oklch(0.14 0.014 290);
--color-tsl13-panel: #1c1a25;
--color-tsl13-panel: oklch(0.17 0.018 290);
--color-tsl13-ink: #e9e7ef;
--color-tsl13-ink: oklch(0.93 0.005 290);
--color-tsl13-mut: #99949f;
--color-tsl13-mut: oklch(0.63 0.012 290);
--color-tsl13-faint: #6f6b76;
--color-tsl13-faint: oklch(0.5 0.01 290);
--color-tsl13-line: #3a3545;
--color-tsl13-line: oklch(0.28 0.018 290);
--color-tsl13-accent: #b07ae8;
--color-tsl13-accent: oklch(0.7 0.16 300);
--color-tsl13-hover: rgb(233 231 239 / 0.06);
--color-tsl13-hover: color-mix(in oklab, oklch(0.93 0.005 290) 6%, transparent);
--color-tsl13-tint: rgb(176 122 232 / 0.17);
--color-tsl13-tint: color-mix(in oklab, oklch(0.7 0.16 300) 17%, transparent);
--font-tsl13-sans: 'Plus Jakarta Sans', system-ui, sans-serif;
--font-tsl13-mono: 'JetBrains Mono', ui-monospace, monospace;
}
.tsl-13 {
width: 100%;
height: 100svh;
min-height: 100svh;
color-scheme: dark;
}@import "tailwindcss";
@theme {
--color-tsl13-bg: #16141c;
--color-tsl13-bg: oklch(0.14 0.014 290);
--color-tsl13-panel: #1c1a25;
--color-tsl13-panel: oklch(0.17 0.018 290);
--color-tsl13-ink: #e9e7ef;
--color-tsl13-ink: oklch(0.93 0.005 290);
--color-tsl13-mut: #99949f;
--color-tsl13-mut: oklch(0.63 0.012 290);
--color-tsl13-faint: #6f6b76;
--color-tsl13-faint: oklch(0.5 0.01 290);
--color-tsl13-line: #3a3545;
--color-tsl13-line: oklch(0.28 0.018 290);
--color-tsl13-accent: #b07ae8;
--color-tsl13-accent: oklch(0.7 0.16 300);
--color-tsl13-hover: rgb(233 231 239 / 0.06);
--color-tsl13-hover: color-mix(in oklab, oklch(0.93 0.005 290) 6%, transparent);
--color-tsl13-tint: rgb(176 122 232 / 0.17);
--color-tsl13-tint: color-mix(in oklab, oklch(0.7 0.16 300) 17%, transparent);
--font-tsl13-sans: 'Plus Jakarta Sans', system-ui, sans-serif;
--font-tsl13-mono: 'JetBrains Mono', ui-monospace, monospace;
}
.tsl-13 {
width: 100%;
height: 100svh;
min-height: 100svh;
color-scheme: dark;
}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-tsl13-bg: #16141c;
--color-tsl13-bg: oklch(0.14 0.014 290);
--color-tsl13-panel: #1c1a25;
--color-tsl13-panel: oklch(0.17 0.018 290);
--color-tsl13-ink: #e9e7ef;
--color-tsl13-ink: oklch(0.93 0.005 290);
--color-tsl13-mut: #99949f;
--color-tsl13-mut: oklch(0.63 0.012 290);
--color-tsl13-faint: #6f6b76;
--color-tsl13-faint: oklch(0.5 0.01 290);
--color-tsl13-line: #3a3545;
--color-tsl13-line: oklch(0.28 0.018 290);
--color-tsl13-accent: #b07ae8;
--color-tsl13-accent: oklch(0.7 0.16 300);
--color-tsl13-hover: rgb(233 231 239 / 0.06);
--color-tsl13-hover: color-mix(in oklab, oklch(0.93 0.005 290) 6%, transparent);
--color-tsl13-tint: rgb(176 122 232 / 0.17);
--color-tsl13-tint: color-mix(in oklab, oklch(0.7 0.16 300) 17%, transparent);
--font-tsl13-sans: 'Plus Jakarta Sans', system-ui, sans-serif;
--font-tsl13-mono: 'JetBrains Mono', ui-monospace, monospace;
}
.tsl-13 {
width: 100%;
height: 100svh;
min-height: 100svh;
color-scheme: dark;
}@import "tailwindcss";
@theme {
--color-tsl13-bg: #16141c;
--color-tsl13-bg: oklch(0.14 0.014 290);
--color-tsl13-panel: #1c1a25;
--color-tsl13-panel: oklch(0.17 0.018 290);
--color-tsl13-ink: #e9e7ef;
--color-tsl13-ink: oklch(0.93 0.005 290);
--color-tsl13-mut: #99949f;
--color-tsl13-mut: oklch(0.63 0.012 290);
--color-tsl13-faint: #6f6b76;
--color-tsl13-faint: oklch(0.5 0.01 290);
--color-tsl13-line: #3a3545;
--color-tsl13-line: oklch(0.28 0.018 290);
--color-tsl13-accent: #b07ae8;
--color-tsl13-accent: oklch(0.7 0.16 300);
--color-tsl13-hover: rgb(233 231 239 / 0.06);
--color-tsl13-hover: color-mix(in oklab, oklch(0.93 0.005 290) 6%, transparent);
--color-tsl13-tint: rgb(176 122 232 / 0.17);
--color-tsl13-tint: color-mix(in oklab, oklch(0.7 0.16 300) 17%, transparent);
--font-tsl13-sans: 'Plus Jakarta Sans', system-ui, sans-serif;
--font-tsl13-mono: 'JetBrains Mono', ui-monospace, monospace;
}
.tsl-13 {
width: 100%;
height: 100svh;
min-height: 100svh;
color-scheme: dark;
}<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=Plus+Jakarta+Sans:wght@400;500;600;700;800&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=Plus+Jakarta+Sans:wght@400;500;600;700;800&family=JetBrains+Mono:wght@400;500;600&display=swap">What changed in the port
Which parts became utilities, which stayed CSS, and why.
last:before:hiddenreplacesli:not(:last-child)::before, and is the better spelling: the connector is declared on every item, then removed from the one that must not have it, which is how a reader thinks about a timeline.- The
max-xl:breakpoint replaced a hand-writtenmax-width:1100pxquery. Snapping to the scale (1280px) is a small visual change and a large maintenance one — one fewer magic number in the file. - UI change from the CSS original: nav rows went from 8px padding to
min-h-11, the timeline timestamp got its own token instead of acolor-mixof a muted colour (which was landing near 3:1), and badges keep full-opacity white on the accent fill.
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 Dual Sidebar App Shell with Left Nav and Context Panel
Source: https://codefronts.com/layouts/tailwind-css-sidebar-layouts/tailwind-dual-sidebar-app-shell-context-panel/
The Notion/Discord-class shell: primary nav left, contextual panel right, content between. The most valuable line in the demo is minmax(0,1fr) on the middle track — the answer to the most-asked grid question on the internet, and one that reads more clearly as a utility than as CSS.
## HTML
```html
<section class="tsl-13 w-full h-svh min-h-svh grid grid-cols-[232px_minmax(0,1fr)_280px] max-xl:grid-cols-[232px_minmax(0,1fr)] font-tsl13-sans bg-tsl13-bg text-tsl13-ink">
<aside aria-label="Workspace" class="bg-tsl13-panel border-r border-tsl13-line px-2.5 py-4 overflow-y-auto">
<div class="flex items-center gap-2.5 px-2.5 pt-0.5 pb-4 text-[14.5px] font-bold tracking-tight"><span aria-hidden="true" class="grid place-items-center w-[26px] h-[26px] rounded-lg text-xs font-bold text-white bg-[linear-gradient(135deg,var(--color-tsl13-accent),oklch(0.6_0.18_260))]">L</span>Loomcraft</div>
<div class="px-2.5 pt-3.5 pb-1.5 text-[10.5px] font-semibold uppercase tracking-[0.09em] text-tsl13-mut">Projects</div>
<nav class="flex flex-col gap-px">
<a href="#" aria-current="page" class="flex items-center min-h-11 px-3 rounded-lg text-[13.5px] font-medium text-tsl13-mut no-underline transition-colors duration-150 hover:text-tsl13-ink hover:bg-tsl13-hover aria-[current=page]:text-tsl13-ink aria-[current=page]:bg-tsl13-tint focus-visible:outline-2 focus-visible:outline-tsl13-accent focus-visible:outline-offset-1"># brand-refresh <span class="ml-auto rounded-full px-[7px] py-[3px] text-[10.5px] font-bold text-white bg-tsl13-accent">3</span></a>
<a href="#" class="flex items-center min-h-11 px-3 rounded-lg text-[13.5px] font-medium text-tsl13-mut no-underline transition-colors duration-150 hover:text-tsl13-ink hover:bg-tsl13-hover focus-visible:outline-2 focus-visible:outline-tsl13-accent focus-visible:outline-offset-1"># website-v4</a>
<a href="#" class="flex items-center min-h-11 px-3 rounded-lg text-[13.5px] font-medium text-tsl13-mut no-underline transition-colors duration-150 hover:text-tsl13-ink hover:bg-tsl13-hover focus-visible:outline-2 focus-visible:outline-tsl13-accent focus-visible:outline-offset-1"># mobile-app <span class="ml-auto rounded-full px-[7px] py-[3px] text-[10.5px] font-bold text-white bg-tsl13-accent">12</span></a>
</nav>
<div class="px-2.5 pt-3.5 pb-1.5 text-[10.5px] font-semibold uppercase tracking-[0.09em] text-tsl13-mut">Team</div>
<nav class="flex flex-col gap-px">
<a href="#" class="flex items-center min-h-11 px-3 rounded-lg text-[13.5px] font-medium text-tsl13-mut no-underline transition-colors duration-150 hover:text-tsl13-ink hover:bg-tsl13-hover focus-visible:outline-2 focus-visible:outline-tsl13-accent focus-visible:outline-offset-1"># design-crit</a>
<a href="#" class="flex items-center min-h-11 px-3 rounded-lg text-[13.5px] font-medium text-tsl13-mut no-underline transition-colors duration-150 hover:text-tsl13-ink hover:bg-tsl13-hover focus-visible:outline-2 focus-visible:outline-tsl13-accent focus-visible:outline-offset-1"># announcements</a>
</nav>
</aside>
<main class="overflow-y-auto px-[34px] py-[30px] [scrollbar-gutter:stable]">
<h1 class="mb-3 text-xl font-bold leading-tight"># brand-refresh</h1>
<p class="max-w-[60ch] text-sm leading-[1.7] text-tsl13-mut text-pretty">The centre track is <code class="font-tsl13-mono text-[12.5px] px-1.5 py-0.5 rounded-[5px] bg-tsl13-hover text-tsl13-ink">minmax(0,1fr)</code> — wide content shrinks and scrolls instead of crushing the context panel. Narrow the window past 1280px: the right panel yields first, the nav survives.</p>
</main>
<aside aria-label="Activity" class="max-xl:hidden border-l border-tsl13-line bg-tsl13-panel px-4 py-5 overflow-y-auto">
<h2 class="mb-4 text-xs font-semibold uppercase tracking-[0.08em] text-tsl13-mut">Activity</h2>
<ol class="list-none m-0 p-0 grid">
<li class="relative grid grid-cols-[28px_1fr] gap-3 pb-5 before:content-[''] before:absolute before:left-[13.5px] before:top-8 before:bottom-0.5 before:w-px before:bg-tsl13-line last:before:hidden"><span aria-hidden="true" class="grid place-items-center w-7 h-7 rounded-full text-[9.5px] font-bold text-white bg-[linear-gradient(135deg,oklch(0.6_0.15_300),oklch(0.55_0.15_240))]">PR</span><div class="text-[12.5px] leading-[1.5] text-tsl13-mut"><strong class="font-semibold text-tsl13-ink">Priya</strong> shipped the new wordmark<time class="block mt-0.5 text-[11px] text-tsl13-faint">2h ago</time></div></li>
<li class="relative grid grid-cols-[28px_1fr] gap-3 pb-5 before:content-[''] before:absolute before:left-[13.5px] before:top-8 before:bottom-0.5 before:w-px before:bg-tsl13-line last:before:hidden"><span aria-hidden="true" class="grid place-items-center w-7 h-7 rounded-full text-[9.5px] font-bold text-white bg-[linear-gradient(135deg,oklch(0.6_0.15_300),oklch(0.55_0.15_240))]">MW</span><div class="text-[12.5px] leading-[1.5] text-tsl13-mut"><strong class="font-semibold text-tsl13-ink">Marcus</strong> commented on palette v3<time class="block mt-0.5 text-[11px] text-tsl13-faint">4h ago</time></div></li>
<li class="relative grid grid-cols-[28px_1fr] gap-3 pb-5 before:content-[''] before:absolute before:left-[13.5px] before:top-8 before:bottom-0.5 before:w-px before:bg-tsl13-line last:before:hidden"><span aria-hidden="true" class="grid place-items-center w-7 h-7 rounded-full text-[9.5px] font-bold text-white bg-[linear-gradient(135deg,oklch(0.6_0.15_300),oklch(0.55_0.15_240))]">AO</span><div class="text-[12.5px] leading-[1.5] text-tsl13-mut"><strong class="font-semibold text-tsl13-ink">Amara</strong> uploaded 6 explorations<time class="block mt-0.5 text-[11px] text-tsl13-faint">Yesterday</time></div></li>
</ol>
</aside>
</section>
```
## CSS
```css
@import "tailwindcss";
@theme {
--color-tsl13-bg: #16141c;
--color-tsl13-bg: oklch(0.14 0.014 290);
--color-tsl13-panel: #1c1a25;
--color-tsl13-panel: oklch(0.17 0.018 290);
--color-tsl13-ink: #e9e7ef;
--color-tsl13-ink: oklch(0.93 0.005 290);
--color-tsl13-mut: #99949f;
--color-tsl13-mut: oklch(0.63 0.012 290);
--color-tsl13-faint: #6f6b76;
--color-tsl13-faint: oklch(0.5 0.01 290);
--color-tsl13-line: #3a3545;
--color-tsl13-line: oklch(0.28 0.018 290);
--color-tsl13-accent: #b07ae8;
--color-tsl13-accent: oklch(0.7 0.16 300);
--color-tsl13-hover: rgb(233 231 239 / 0.06);
--color-tsl13-hover: color-mix(in oklab, oklch(0.93 0.005 290) 6%, transparent);
--color-tsl13-tint: rgb(176 122 232 / 0.17);
--color-tsl13-tint: color-mix(in oklab, oklch(0.7 0.16 300) 17%, transparent);
--font-tsl13-sans: 'Plus Jakarta Sans', system-ui, sans-serif;
--font-tsl13-mono: 'JetBrains Mono', ui-monospace, monospace;
}
.tsl-13 {
width: 100%;
height: 100svh;
min-height: 100svh;
color-scheme: dark;
}
```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 Dual Sidebar App Shell with Left Nav and Context Panel
Source: https://codefronts.com/layouts/tailwind-css-sidebar-layouts/tailwind-dual-sidebar-app-shell-context-panel/
The Notion/Discord-class shell: primary nav left, contextual panel right, content between. The most valuable line in the demo is minmax(0,1fr) on the middle track — the answer to the most-asked grid question on the internet, and one that reads more clearly as a utility than as CSS.
## HTML
```html
<section class="tsl-13 w-full h-svh min-h-svh grid grid-cols-[232px_minmax(0,1fr)_280px] max-xl:grid-cols-[232px_minmax(0,1fr)] font-tsl13-sans bg-tsl13-bg text-tsl13-ink">
<aside aria-label="Workspace" class="bg-tsl13-panel border-r border-tsl13-line px-2.5 py-4 overflow-y-auto">
<div class="flex items-center gap-2.5 px-2.5 pt-0.5 pb-4 text-[14.5px] font-bold tracking-tight"><span aria-hidden="true" class="grid place-items-center w-[26px] h-[26px] rounded-lg text-xs font-bold text-white bg-[linear-gradient(135deg,var(--color-tsl13-accent),oklch(0.6_0.18_260))]">L</span>Loomcraft</div>
<div class="px-2.5 pt-3.5 pb-1.5 text-[10.5px] font-semibold uppercase tracking-[0.09em] text-tsl13-mut">Projects</div>
<nav class="flex flex-col gap-px">
<a href="#" aria-current="page" class="flex items-center min-h-11 px-3 rounded-lg text-[13.5px] font-medium text-tsl13-mut no-underline transition-colors duration-150 hover:text-tsl13-ink hover:bg-tsl13-hover aria-[current=page]:text-tsl13-ink aria-[current=page]:bg-tsl13-tint focus-visible:outline-2 focus-visible:outline-tsl13-accent focus-visible:outline-offset-1"># brand-refresh <span class="ml-auto rounded-full px-[7px] py-[3px] text-[10.5px] font-bold text-white bg-tsl13-accent">3</span></a>
<a href="#" class="flex items-center min-h-11 px-3 rounded-lg text-[13.5px] font-medium text-tsl13-mut no-underline transition-colors duration-150 hover:text-tsl13-ink hover:bg-tsl13-hover focus-visible:outline-2 focus-visible:outline-tsl13-accent focus-visible:outline-offset-1"># website-v4</a>
<a href="#" class="flex items-center min-h-11 px-3 rounded-lg text-[13.5px] font-medium text-tsl13-mut no-underline transition-colors duration-150 hover:text-tsl13-ink hover:bg-tsl13-hover focus-visible:outline-2 focus-visible:outline-tsl13-accent focus-visible:outline-offset-1"># mobile-app <span class="ml-auto rounded-full px-[7px] py-[3px] text-[10.5px] font-bold text-white bg-tsl13-accent">12</span></a>
</nav>
<div class="px-2.5 pt-3.5 pb-1.5 text-[10.5px] font-semibold uppercase tracking-[0.09em] text-tsl13-mut">Team</div>
<nav class="flex flex-col gap-px">
<a href="#" class="flex items-center min-h-11 px-3 rounded-lg text-[13.5px] font-medium text-tsl13-mut no-underline transition-colors duration-150 hover:text-tsl13-ink hover:bg-tsl13-hover focus-visible:outline-2 focus-visible:outline-tsl13-accent focus-visible:outline-offset-1"># design-crit</a>
<a href="#" class="flex items-center min-h-11 px-3 rounded-lg text-[13.5px] font-medium text-tsl13-mut no-underline transition-colors duration-150 hover:text-tsl13-ink hover:bg-tsl13-hover focus-visible:outline-2 focus-visible:outline-tsl13-accent focus-visible:outline-offset-1"># announcements</a>
</nav>
</aside>
<main class="overflow-y-auto px-[34px] py-[30px] [scrollbar-gutter:stable]">
<h1 class="mb-3 text-xl font-bold leading-tight"># brand-refresh</h1>
<p class="max-w-[60ch] text-sm leading-[1.7] text-tsl13-mut text-pretty">The centre track is <code class="font-tsl13-mono text-[12.5px] px-1.5 py-0.5 rounded-[5px] bg-tsl13-hover text-tsl13-ink">minmax(0,1fr)</code> — wide content shrinks and scrolls instead of crushing the context panel. Narrow the window past 1280px: the right panel yields first, the nav survives.</p>
</main>
<aside aria-label="Activity" class="max-xl:hidden border-l border-tsl13-line bg-tsl13-panel px-4 py-5 overflow-y-auto">
<h2 class="mb-4 text-xs font-semibold uppercase tracking-[0.08em] text-tsl13-mut">Activity</h2>
<ol class="list-none m-0 p-0 grid">
<li class="relative grid grid-cols-[28px_1fr] gap-3 pb-5 before:content-[''] before:absolute before:left-[13.5px] before:top-8 before:bottom-0.5 before:w-px before:bg-tsl13-line last:before:hidden"><span aria-hidden="true" class="grid place-items-center w-7 h-7 rounded-full text-[9.5px] font-bold text-white bg-[linear-gradient(135deg,oklch(0.6_0.15_300),oklch(0.55_0.15_240))]">PR</span><div class="text-[12.5px] leading-[1.5] text-tsl13-mut"><strong class="font-semibold text-tsl13-ink">Priya</strong> shipped the new wordmark<time class="block mt-0.5 text-[11px] text-tsl13-faint">2h ago</time></div></li>
<li class="relative grid grid-cols-[28px_1fr] gap-3 pb-5 before:content-[''] before:absolute before:left-[13.5px] before:top-8 before:bottom-0.5 before:w-px before:bg-tsl13-line last:before:hidden"><span aria-hidden="true" class="grid place-items-center w-7 h-7 rounded-full text-[9.5px] font-bold text-white bg-[linear-gradient(135deg,oklch(0.6_0.15_300),oklch(0.55_0.15_240))]">MW</span><div class="text-[12.5px] leading-[1.5] text-tsl13-mut"><strong class="font-semibold text-tsl13-ink">Marcus</strong> commented on palette v3<time class="block mt-0.5 text-[11px] text-tsl13-faint">4h ago</time></div></li>
<li class="relative grid grid-cols-[28px_1fr] gap-3 pb-5 before:content-[''] before:absolute before:left-[13.5px] before:top-8 before:bottom-0.5 before:w-px before:bg-tsl13-line last:before:hidden"><span aria-hidden="true" class="grid place-items-center w-7 h-7 rounded-full text-[9.5px] font-bold text-white bg-[linear-gradient(135deg,oklch(0.6_0.15_300),oklch(0.55_0.15_240))]">AO</span><div class="text-[12.5px] leading-[1.5] text-tsl13-mut"><strong class="font-semibold text-tsl13-ink">Amara</strong> uploaded 6 explorations<time class="block mt-0.5 text-[11px] text-tsl13-faint">Yesterday</time></div></li>
</ol>
</aside>
</section>
```
## CSS
```css
@import "tailwindcss";
@theme {
--color-tsl13-bg: #16141c;
--color-tsl13-bg: oklch(0.14 0.014 290);
--color-tsl13-panel: #1c1a25;
--color-tsl13-panel: oklch(0.17 0.018 290);
--color-tsl13-ink: #e9e7ef;
--color-tsl13-ink: oklch(0.93 0.005 290);
--color-tsl13-mut: #99949f;
--color-tsl13-mut: oklch(0.63 0.012 290);
--color-tsl13-faint: #6f6b76;
--color-tsl13-faint: oklch(0.5 0.01 290);
--color-tsl13-line: #3a3545;
--color-tsl13-line: oklch(0.28 0.018 290);
--color-tsl13-accent: #b07ae8;
--color-tsl13-accent: oklch(0.7 0.16 300);
--color-tsl13-hover: rgb(233 231 239 / 0.06);
--color-tsl13-hover: color-mix(in oklab, oklch(0.93 0.005 290) 6%, transparent);
--color-tsl13-tint: rgb(176 122 232 / 0.17);
--color-tsl13-tint: color-mix(in oklab, oklch(0.7 0.16 300) 17%, transparent);
--font-tsl13-sans: 'Plus Jakarta Sans', system-ui, sans-serif;
--font-tsl13-mono: 'JetBrains Mono', ui-monospace, monospace;
}
.tsl-13 {
width: 100%;
height: 100svh;
min-height: 100svh;
color-scheme: dark;
}
```How this works
One declaration is the architecture. Three tracks, the middle one minmax(0,1fr) so it can actually shrink, and each pane scrolling on its own. Write grid-cols-[232px_1fr_280px] instead and a single wide <pre> pushes the context panel off-screen; the utility form puts the fix in the same string as the widths, where it is hard to lose in a refactor.
The breakpoints encode hierarchy. At the xl boundary the context panel disappears entirely (max-xl:hidden, not invisible, so its tab stops leave the keyboard order too) while the left nav survives — that ordering is the product decision the layout is making.
Make it yours
- 232/280 are the Notion-ish defaults; chat products run a 72px icon rail plus a 240px channel list — see demo 28.
- User-collapsible right panel: mirror demo 02 with
has-checked:grid-cols-[232px_minmax(0,1fr)_0px]. - Swap
max-xl:for a container variant if the shell embeds in a resizable workspace.
Gotchas — read before shipping
minmax(0,1fr)is not optional on any grid track that holds arbitrary content.- Hide the panel with
hidden, neverinvisible— invisible content keeps its tab stops. - Both hairlines need 3:1 against both neighbours; a single low-contrast border token shared by two different backgrounds usually fails one of them.
Browser support
| Chrome | Safari | Firefox | Edge |
|---|---|---|---|
| 111+ | 16.4+ | 128+ | 111+ |
Baseline grid throughout — nothing gated beyond Tailwind v4's own floor.