18 / 20
All 20 in 20 Tailwind CSS Sidebars
- 01Tailwind Accessible Sidebar Navigation ARIA Reference
- 02Tailwind Sidebar Focus Trap and Restore on Close
- 03Tailwind Inert Background Content Behind a Drawer
- 04Tailwind Sidebar Navigation Is Not a Tab List
- 05Tailwind Announcing Collapsed and Expanded Sidebar State
- 06Tailwind Roving Tabindex for Sidebar Keyboard Navigation
- 07Tailwind Persisting Sidebar Collapse State Across Reloads
- 08Tailwind Sidebar Scroll Containment with Overscroll Behavior
- 09Tailwind Nested Submenu Keyboard and Screen Reader Behavior
- 10Tailwind Resizable Sidebar with a Keyboard Accessible Handle
- 11Pure Tailwind Collapsible Sidebar with Checkbox State
- 12Tailwind Responsive Sidebar Breakpoint Behavior
- 13Pure Tailwind Icon Rail Sidebar with Accessible Labels
- 14Tailwind Dashboard Sidebar with Current Page State
- 15Pure Tailwind Multi Level Sidebar Menu Disclosure Pattern
- 16Pure Tailwind Accordion Sidebar with Details and Summary
- 17Pure Tailwind Sticky Full Height Sidebar Layout Mechanics
- 18Pure Tailwind Floating Sidebar Stacking and Overlay Order
- 19Tailwind Off Canvas Sidebar Drawer with Focus Return
- 20Pure Tailwind Sidebar Footer Pinning with Scrollable Nav
Pure Tailwind Floating Sidebar Stacking and Overlay Order
A detached, glassy panel floating over the content — and the reason it is a machinery demo rather than a looks demo is isolate. The scene declares itself a stacking context on purpose, so the panel's z- values are resolved locally and cannot be outranked by something unrelated elsewhere on the page. The whole thing is utilities, including the blur.
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="tsb-18 block relative w-full min-h-svh bg-tsb18-bg text-tsb18-ink font-tsb18-sans leading-[1.55]" aria-label="Nova stage">
<div class="absolute top-3.5 right-3.5 z-90">
<input class="tsb-18-theme-input peer absolute inset-0 w-full h-full m-0 opacity-0 cursor-pointer" type="checkbox" id="tsb-18-theme">
<label class="grid place-items-center w-11 h-11 rounded-[0.9rem] border border-tsb18-line bg-tsb18-surf text-tsb18-ink cursor-pointer peer-focus-visible:outline-2 peer-focus-visible:outline-tsb18-acc peer-focus-visible:outline-offset-2" for="tsb-18-theme">
<svg class="w-4.5 h-4.5" viewBox="0 0 24 24" aria-hidden="true" focusable="false"><circle cx="12" cy="12" r="8.5" fill="none" stroke="currentColor" stroke-width="1.6"/><path d="M12 3.5a8.5 8.5 0 0 0 0 17Z" fill="currentColor"/></svg>
<span class="absolute w-px h-px overflow-hidden whitespace-nowrap [clip-path:inset(50%)]">Toggle dark theme</span>
</label>
</div>
<div class="relative isolate overflow-hidden min-h-svh p-5 bg-tsb18-surf r46:p-8">
<div class="min-w-0 pr-16 r46:pr-68 max-r32:pr-0" id="tsb-18-lib">
<p class="m-0 mb-3.5 font-tsb18-display text-[0.78rem] tracking-[0.16em] uppercase text-tsb18-mut">Continue watching</p>
<div class="grid grid-cols-[repeat(auto-fill,minmax(8.5rem,1fr))] gap-3 [&>article]:min-w-0 [&>article]:aspect-[3/4] [&>article]:flex [&>article]:flex-col [&>article]:justify-end [&>article]:gap-0.5 [&>article]:p-2.5 [&>article]:rounded-[0.8rem] [&>article]:bg-tsb18-bg [&>article]:border [&>article]:border-tsb18-line [&_p]:m-0 [&_p]:min-w-0 [&_p]:text-[0.88rem] [&_p]:font-semibold [&_span]:text-[0.74rem] [&_span]:text-tsb18-mut">
<article class="!border-tsb18-acc"><p>Harbour Wall</p><span>ep 4</span></article>
<article><p>Field Recordings</p><span>ep 11</span></article>
<article><p>Slack Water</p><span>ep 2</span></article>
<article><p>Kestrel</p><span>ep 7</span></article>
<article><p>Two Bells</p><span>ep 1</span></article>
<article><p>Low Tide</p><span>ep 9</span></article>
</div>
</div>
<div class="absolute inset-0 z-20 pointer-events-none max-r32:static">
<div class="absolute inset-0 z-30 bg-[oklch(14%_0.03_260/0.28)] max-r32:hidden" aria-hidden="true"></div>
<nav class="absolute z-40 inset-y-6 right-6 w-[min(14.5rem,62%)] pointer-events-auto flex flex-col p-3 rounded-2xl border border-tsb18-line bg-tsb18-glass backdrop-blur-[14px] backdrop-saturate-150 shadow-[0_1.2rem_2.6rem_oklch(10%_0.02_260/0.45)] max-r32:static max-r32:w-full max-r32:mt-4" aria-label="Nova library">
<p class="m-0 mb-2.5 font-tsb18-display text-[0.7rem] tracking-[0.18em] uppercase text-tsb18-mut">Library</p>
<ul class="list-none m-0 p-0 grid gap-0.5">
<li><a class="flex items-center min-w-0 min-h-11 px-2.5 py-2 rounded-[0.7rem] text-[0.88rem] text-tsb18-ink no-underline hover:bg-tsb18-accsoft focus-visible:outline-2 focus-visible:outline-tsb18-acc focus-visible:outline-offset-2 aria-[current=page]:bg-tsb18-acc aria-[current=page]:text-tsb18-onacc aria-[current=page]:font-semibold" href="#tsb-18-lib" aria-current="page">Continue watching</a></li>
<li><a class="flex items-center min-w-0 min-h-11 px-2.5 py-2 rounded-[0.7rem] text-[0.88rem] text-tsb18-ink no-underline hover:bg-tsb18-accsoft focus-visible:outline-2 focus-visible:outline-tsb18-acc focus-visible:outline-offset-2" href="#tsb-18-lib">My list</a></li>
<li><a class="flex items-center min-w-0 min-h-11 px-2.5 py-2 rounded-[0.7rem] text-[0.88rem] text-tsb18-ink no-underline hover:bg-tsb18-accsoft focus-visible:outline-2 focus-visible:outline-tsb18-acc focus-visible:outline-offset-2" href="#tsb-18-lib">Downloads</a></li>
<li><a class="flex items-center min-w-0 min-h-11 px-2.5 py-2 rounded-[0.7rem] text-[0.88rem] text-tsb18-ink no-underline hover:bg-tsb18-accsoft focus-visible:outline-2 focus-visible:outline-tsb18-acc focus-visible:outline-offset-2" href="#tsb-18-lib">Channels</a></li>
<li><a class="flex items-center min-w-0 min-h-11 px-2.5 py-2 rounded-[0.7rem] text-[0.88rem] text-tsb18-ink no-underline hover:bg-tsb18-accsoft focus-visible:outline-2 focus-visible:outline-tsb18-acc focus-visible:outline-offset-2" href="#tsb-18-lib">Settings</a></li>
</ul>
</nav>
</div>
</div>
</section><section class="tsb-18 block relative w-full min-h-svh bg-tsb18-bg text-tsb18-ink font-tsb18-sans leading-[1.55]" aria-label="Nova stage">
<div class="absolute top-3.5 right-3.5 z-90">
<input class="tsb-18-theme-input peer absolute inset-0 w-full h-full m-0 opacity-0 cursor-pointer" type="checkbox" id="tsb-18-theme">
<label class="grid place-items-center w-11 h-11 rounded-[0.9rem] border border-tsb18-line bg-tsb18-surf text-tsb18-ink cursor-pointer peer-focus-visible:outline-2 peer-focus-visible:outline-tsb18-acc peer-focus-visible:outline-offset-2" for="tsb-18-theme">
<svg class="w-4.5 h-4.5" viewBox="0 0 24 24" aria-hidden="true" focusable="false"><circle cx="12" cy="12" r="8.5" fill="none" stroke="currentColor" stroke-width="1.6"/><path d="M12 3.5a8.5 8.5 0 0 0 0 17Z" fill="currentColor"/></svg>
<span class="absolute w-px h-px overflow-hidden whitespace-nowrap [clip-path:inset(50%)]">Toggle dark theme</span>
</label>
</div>
<div class="relative isolate overflow-hidden min-h-svh p-5 bg-tsb18-surf r46:p-8">
<div class="min-w-0 pr-16 r46:pr-68 max-r32:pr-0" id="tsb-18-lib">
<p class="m-0 mb-3.5 font-tsb18-display text-[0.78rem] tracking-[0.16em] uppercase text-tsb18-mut">Continue watching</p>
<div class="grid grid-cols-[repeat(auto-fill,minmax(8.5rem,1fr))] gap-3 [&>article]:min-w-0 [&>article]:aspect-[3/4] [&>article]:flex [&>article]:flex-col [&>article]:justify-end [&>article]:gap-0.5 [&>article]:p-2.5 [&>article]:rounded-[0.8rem] [&>article]:bg-tsb18-bg [&>article]:border [&>article]:border-tsb18-line [&_p]:m-0 [&_p]:min-w-0 [&_p]:text-[0.88rem] [&_p]:font-semibold [&_span]:text-[0.74rem] [&_span]:text-tsb18-mut">
<article class="!border-tsb18-acc"><p>Harbour Wall</p><span>ep 4</span></article>
<article><p>Field Recordings</p><span>ep 11</span></article>
<article><p>Slack Water</p><span>ep 2</span></article>
<article><p>Kestrel</p><span>ep 7</span></article>
<article><p>Two Bells</p><span>ep 1</span></article>
<article><p>Low Tide</p><span>ep 9</span></article>
</div>
</div>
<div class="absolute inset-0 z-20 pointer-events-none max-r32:static">
<div class="absolute inset-0 z-30 bg-[oklch(14%_0.03_260/0.28)] max-r32:hidden" aria-hidden="true"></div>
<nav class="absolute z-40 inset-y-6 right-6 w-[min(14.5rem,62%)] pointer-events-auto flex flex-col p-3 rounded-2xl border border-tsb18-line bg-tsb18-glass backdrop-blur-[14px] backdrop-saturate-150 shadow-[0_1.2rem_2.6rem_oklch(10%_0.02_260/0.45)] max-r32:static max-r32:w-full max-r32:mt-4" aria-label="Nova library">
<p class="m-0 mb-2.5 font-tsb18-display text-[0.7rem] tracking-[0.18em] uppercase text-tsb18-mut">Library</p>
<ul class="list-none m-0 p-0 grid gap-0.5">
<li><a class="flex items-center min-w-0 min-h-11 px-2.5 py-2 rounded-[0.7rem] text-[0.88rem] text-tsb18-ink no-underline hover:bg-tsb18-accsoft focus-visible:outline-2 focus-visible:outline-tsb18-acc focus-visible:outline-offset-2 aria-[current=page]:bg-tsb18-acc aria-[current=page]:text-tsb18-onacc aria-[current=page]:font-semibold" href="#tsb-18-lib" aria-current="page">Continue watching</a></li>
<li><a class="flex items-center min-w-0 min-h-11 px-2.5 py-2 rounded-[0.7rem] text-[0.88rem] text-tsb18-ink no-underline hover:bg-tsb18-accsoft focus-visible:outline-2 focus-visible:outline-tsb18-acc focus-visible:outline-offset-2" href="#tsb-18-lib">My list</a></li>
<li><a class="flex items-center min-w-0 min-h-11 px-2.5 py-2 rounded-[0.7rem] text-[0.88rem] text-tsb18-ink no-underline hover:bg-tsb18-accsoft focus-visible:outline-2 focus-visible:outline-tsb18-acc focus-visible:outline-offset-2" href="#tsb-18-lib">Downloads</a></li>
<li><a class="flex items-center min-w-0 min-h-11 px-2.5 py-2 rounded-[0.7rem] text-[0.88rem] text-tsb18-ink no-underline hover:bg-tsb18-accsoft focus-visible:outline-2 focus-visible:outline-tsb18-acc focus-visible:outline-offset-2" href="#tsb-18-lib">Channels</a></li>
<li><a class="flex items-center min-w-0 min-h-11 px-2.5 py-2 rounded-[0.7rem] text-[0.88rem] text-tsb18-ink no-underline hover:bg-tsb18-accsoft focus-visible:outline-2 focus-visible:outline-tsb18-acc focus-visible:outline-offset-2" href="#tsb-18-lib">Settings</a></li>
</ul>
</nav>
</div>
</div>
</section>@import "tailwindcss";
@theme {
--color-tsb18-bg: #070c1a;
--color-tsb18-bg: oklch(13% 0.03 265);
--color-tsb18-surf: #0e1730;
--color-tsb18-surf: oklch(19% 0.04 265);
--color-tsb18-glass: rgba(20, 32, 64, 0.62);
--color-tsb18-glass: oklch(25% 0.05 265 / 0.62);
--color-tsb18-line: #1f2c4d;
--color-tsb18-line: oklch(28% 0.045 265);
--color-tsb18-ink: #e8ecfa;
--color-tsb18-ink: oklch(93% 0.015 265);
--color-tsb18-mut: #8e9bc0;
--color-tsb18-mut: oklch(67% 0.035 265);
--color-tsb18-acc: #6ff2d0;
--color-tsb18-acc: oklch(88% 0.13 172);
--color-tsb18-accsoft: #10332f;
--color-tsb18-accsoft: oklch(28% 0.05 172);
--color-tsb18-onacc: #070c1a;
--color-tsb18-onacc: oklch(13% 0.03 265);
--font-tsb18-sans: system-ui, -apple-system, 'Segoe UI', sans-serif;
--font-tsb18-display: 'Barlow', 'Helvetica Neue', Helvetica, Arial, sans-serif;
--breakpoint-r32: 32rem;
--breakpoint-r46: 46rem;
}
/* Root rule: the full-bleed contract, stated in CSS as well as in the markup's
w-full min-h-svh. */
.tsb-18 {
width: 100%;
min-height: 100svh;
}
.tsb-18 *,
.tsb-18 *::before,
.tsb-18 *::after {
box-sizing: border-box;
}
/* Dark-first demo: the @theme block IS the dark palette, light mirror below. The glass
token carries its own alpha, because backdrop-blur alone is not glass. */
.tsb-18:has(.tsb-18-theme-input:checked) {
--color-tsb18-bg: #eef1f8;
--color-tsb18-surf: #ffffff;
--color-tsb18-glass: oklch(100% 0 0 / 0.68);
--color-tsb18-line: #d3d9e8;
--color-tsb18-ink: #101527;
--color-tsb18-mut: #565f7a;
--color-tsb18-acc: #0a6f5c;
--color-tsb18-acc: oklch(46% 0.1 172);
--color-tsb18-accsoft: #d3ece6;
--color-tsb18-onacc: #ffffff;
}
@media (prefers-color-scheme: light) {
.tsb-18 {
--color-tsb18-bg: #eef1f8;
--color-tsb18-surf: #ffffff;
--color-tsb18-glass: oklch(100% 0 0 / 0.68);
--color-tsb18-line: #d3d9e8;
--color-tsb18-ink: #101527;
--color-tsb18-mut: #565f7a;
--color-tsb18-acc: #0a6f5c;
--color-tsb18-acc: oklch(46% 0.1 172);
--color-tsb18-accsoft: #d3ece6;
--color-tsb18-onacc: #ffffff;
}
.tsb-18:has(.tsb-18-theme-input:checked) {
--color-tsb18-bg: #070c1a;
--color-tsb18-surf: #0e1730;
--color-tsb18-glass: oklch(25% 0.05 265 / 0.62);
--color-tsb18-line: #1f2c4d;
--color-tsb18-ink: #e8ecfa;
--color-tsb18-mut: #8e9bc0;
--color-tsb18-acc: #6ff2d0;
--color-tsb18-acc: oklch(88% 0.13 172);
--color-tsb18-accsoft: #10332f;
--color-tsb18-onacc: #070c1a;
}
}
@media (prefers-color-scheme: dark) {
.tsb-18:has(.tsb-18-theme-input:checked) {
--color-tsb18-bg: #eef1f8;
--color-tsb18-surf: #ffffff;
--color-tsb18-glass: oklch(100% 0 0 / 0.68);
--color-tsb18-line: #d3d9e8;
--color-tsb18-ink: #101527;
--color-tsb18-mut: #565f7a;
--color-tsb18-acc: #0a6f5c;
--color-tsb18-acc: oklch(46% 0.1 172);
--color-tsb18-accsoft: #d3ece6;
--color-tsb18-onacc: #ffffff;
}
}@import "tailwindcss";
@theme {
--color-tsb18-bg: #070c1a;
--color-tsb18-bg: oklch(13% 0.03 265);
--color-tsb18-surf: #0e1730;
--color-tsb18-surf: oklch(19% 0.04 265);
--color-tsb18-glass: rgba(20, 32, 64, 0.62);
--color-tsb18-glass: oklch(25% 0.05 265 / 0.62);
--color-tsb18-line: #1f2c4d;
--color-tsb18-line: oklch(28% 0.045 265);
--color-tsb18-ink: #e8ecfa;
--color-tsb18-ink: oklch(93% 0.015 265);
--color-tsb18-mut: #8e9bc0;
--color-tsb18-mut: oklch(67% 0.035 265);
--color-tsb18-acc: #6ff2d0;
--color-tsb18-acc: oklch(88% 0.13 172);
--color-tsb18-accsoft: #10332f;
--color-tsb18-accsoft: oklch(28% 0.05 172);
--color-tsb18-onacc: #070c1a;
--color-tsb18-onacc: oklch(13% 0.03 265);
--font-tsb18-sans: system-ui, -apple-system, 'Segoe UI', sans-serif;
--font-tsb18-display: 'Barlow', 'Helvetica Neue', Helvetica, Arial, sans-serif;
--breakpoint-r32: 32rem;
--breakpoint-r46: 46rem;
}
/* Root rule: the full-bleed contract, stated in CSS as well as in the markup's
w-full min-h-svh. */
.tsb-18 {
width: 100%;
min-height: 100svh;
}
.tsb-18 *,
.tsb-18 *::before,
.tsb-18 *::after {
box-sizing: border-box;
}
/* Dark-first demo: the @theme block IS the dark palette, light mirror below. The glass
token carries its own alpha, because backdrop-blur alone is not glass. */
.tsb-18:has(.tsb-18-theme-input:checked) {
--color-tsb18-bg: #eef1f8;
--color-tsb18-surf: #ffffff;
--color-tsb18-glass: oklch(100% 0 0 / 0.68);
--color-tsb18-line: #d3d9e8;
--color-tsb18-ink: #101527;
--color-tsb18-mut: #565f7a;
--color-tsb18-acc: #0a6f5c;
--color-tsb18-acc: oklch(46% 0.1 172);
--color-tsb18-accsoft: #d3ece6;
--color-tsb18-onacc: #ffffff;
}
@media (prefers-color-scheme: light) {
.tsb-18 {
--color-tsb18-bg: #eef1f8;
--color-tsb18-surf: #ffffff;
--color-tsb18-glass: oklch(100% 0 0 / 0.68);
--color-tsb18-line: #d3d9e8;
--color-tsb18-ink: #101527;
--color-tsb18-mut: #565f7a;
--color-tsb18-acc: #0a6f5c;
--color-tsb18-acc: oklch(46% 0.1 172);
--color-tsb18-accsoft: #d3ece6;
--color-tsb18-onacc: #ffffff;
}
.tsb-18:has(.tsb-18-theme-input:checked) {
--color-tsb18-bg: #070c1a;
--color-tsb18-surf: #0e1730;
--color-tsb18-glass: oklch(25% 0.05 265 / 0.62);
--color-tsb18-line: #1f2c4d;
--color-tsb18-ink: #e8ecfa;
--color-tsb18-mut: #8e9bc0;
--color-tsb18-acc: #6ff2d0;
--color-tsb18-acc: oklch(88% 0.13 172);
--color-tsb18-accsoft: #10332f;
--color-tsb18-onacc: #070c1a;
}
}
@media (prefers-color-scheme: dark) {
.tsb-18:has(.tsb-18-theme-input:checked) {
--color-tsb18-bg: #eef1f8;
--color-tsb18-surf: #ffffff;
--color-tsb18-glass: oklch(100% 0 0 / 0.68);
--color-tsb18-line: #d3d9e8;
--color-tsb18-ink: #101527;
--color-tsb18-mut: #565f7a;
--color-tsb18-acc: #0a6f5c;
--color-tsb18-acc: oklch(46% 0.1 172);
--color-tsb18-accsoft: #d3ece6;
--color-tsb18-onacc: #ffffff;
}
}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-tsb18-bg: #070c1a;
--color-tsb18-bg: oklch(13% 0.03 265);
--color-tsb18-surf: #0e1730;
--color-tsb18-surf: oklch(19% 0.04 265);
--color-tsb18-glass: rgba(20, 32, 64, 0.62);
--color-tsb18-glass: oklch(25% 0.05 265 / 0.62);
--color-tsb18-line: #1f2c4d;
--color-tsb18-line: oklch(28% 0.045 265);
--color-tsb18-ink: #e8ecfa;
--color-tsb18-ink: oklch(93% 0.015 265);
--color-tsb18-mut: #8e9bc0;
--color-tsb18-mut: oklch(67% 0.035 265);
--color-tsb18-acc: #6ff2d0;
--color-tsb18-acc: oklch(88% 0.13 172);
--color-tsb18-accsoft: #10332f;
--color-tsb18-accsoft: oklch(28% 0.05 172);
--color-tsb18-onacc: #070c1a;
--color-tsb18-onacc: oklch(13% 0.03 265);
--font-tsb18-sans: system-ui, -apple-system, 'Segoe UI', sans-serif;
--font-tsb18-display: 'Barlow', 'Helvetica Neue', Helvetica, Arial, sans-serif;
--breakpoint-r32: 32rem;
--breakpoint-r46: 46rem;
}
/* Root rule: the full-bleed contract, stated in CSS as well as in the markup's
w-full min-h-svh. */
.tsb-18 {
width: 100%;
min-height: 100svh;
}
.tsb-18 *,
.tsb-18 *::before,
.tsb-18 *::after {
box-sizing: border-box;
}
/* Dark-first demo: the @theme block IS the dark palette, light mirror below. The glass
token carries its own alpha, because backdrop-blur alone is not glass. */
.tsb-18:has(.tsb-18-theme-input:checked) {
--color-tsb18-bg: #eef1f8;
--color-tsb18-surf: #ffffff;
--color-tsb18-glass: oklch(100% 0 0 / 0.68);
--color-tsb18-line: #d3d9e8;
--color-tsb18-ink: #101527;
--color-tsb18-mut: #565f7a;
--color-tsb18-acc: #0a6f5c;
--color-tsb18-acc: oklch(46% 0.1 172);
--color-tsb18-accsoft: #d3ece6;
--color-tsb18-onacc: #ffffff;
}
@media (prefers-color-scheme: light) {
.tsb-18 {
--color-tsb18-bg: #eef1f8;
--color-tsb18-surf: #ffffff;
--color-tsb18-glass: oklch(100% 0 0 / 0.68);
--color-tsb18-line: #d3d9e8;
--color-tsb18-ink: #101527;
--color-tsb18-mut: #565f7a;
--color-tsb18-acc: #0a6f5c;
--color-tsb18-acc: oklch(46% 0.1 172);
--color-tsb18-accsoft: #d3ece6;
--color-tsb18-onacc: #ffffff;
}
.tsb-18:has(.tsb-18-theme-input:checked) {
--color-tsb18-bg: #070c1a;
--color-tsb18-surf: #0e1730;
--color-tsb18-glass: oklch(25% 0.05 265 / 0.62);
--color-tsb18-line: #1f2c4d;
--color-tsb18-ink: #e8ecfa;
--color-tsb18-mut: #8e9bc0;
--color-tsb18-acc: #6ff2d0;
--color-tsb18-acc: oklch(88% 0.13 172);
--color-tsb18-accsoft: #10332f;
--color-tsb18-onacc: #070c1a;
}
}
@media (prefers-color-scheme: dark) {
.tsb-18:has(.tsb-18-theme-input:checked) {
--color-tsb18-bg: #eef1f8;
--color-tsb18-surf: #ffffff;
--color-tsb18-glass: oklch(100% 0 0 / 0.68);
--color-tsb18-line: #d3d9e8;
--color-tsb18-ink: #101527;
--color-tsb18-mut: #565f7a;
--color-tsb18-acc: #0a6f5c;
--color-tsb18-acc: oklch(46% 0.1 172);
--color-tsb18-accsoft: #d3ece6;
--color-tsb18-onacc: #ffffff;
}
}@import "tailwindcss";
@theme {
--color-tsb18-bg: #070c1a;
--color-tsb18-bg: oklch(13% 0.03 265);
--color-tsb18-surf: #0e1730;
--color-tsb18-surf: oklch(19% 0.04 265);
--color-tsb18-glass: rgba(20, 32, 64, 0.62);
--color-tsb18-glass: oklch(25% 0.05 265 / 0.62);
--color-tsb18-line: #1f2c4d;
--color-tsb18-line: oklch(28% 0.045 265);
--color-tsb18-ink: #e8ecfa;
--color-tsb18-ink: oklch(93% 0.015 265);
--color-tsb18-mut: #8e9bc0;
--color-tsb18-mut: oklch(67% 0.035 265);
--color-tsb18-acc: #6ff2d0;
--color-tsb18-acc: oklch(88% 0.13 172);
--color-tsb18-accsoft: #10332f;
--color-tsb18-accsoft: oklch(28% 0.05 172);
--color-tsb18-onacc: #070c1a;
--color-tsb18-onacc: oklch(13% 0.03 265);
--font-tsb18-sans: system-ui, -apple-system, 'Segoe UI', sans-serif;
--font-tsb18-display: 'Barlow', 'Helvetica Neue', Helvetica, Arial, sans-serif;
--breakpoint-r32: 32rem;
--breakpoint-r46: 46rem;
}
/* Root rule: the full-bleed contract, stated in CSS as well as in the markup's
w-full min-h-svh. */
.tsb-18 {
width: 100%;
min-height: 100svh;
}
.tsb-18 *,
.tsb-18 *::before,
.tsb-18 *::after {
box-sizing: border-box;
}
/* Dark-first demo: the @theme block IS the dark palette, light mirror below. The glass
token carries its own alpha, because backdrop-blur alone is not glass. */
.tsb-18:has(.tsb-18-theme-input:checked) {
--color-tsb18-bg: #eef1f8;
--color-tsb18-surf: #ffffff;
--color-tsb18-glass: oklch(100% 0 0 / 0.68);
--color-tsb18-line: #d3d9e8;
--color-tsb18-ink: #101527;
--color-tsb18-mut: #565f7a;
--color-tsb18-acc: #0a6f5c;
--color-tsb18-acc: oklch(46% 0.1 172);
--color-tsb18-accsoft: #d3ece6;
--color-tsb18-onacc: #ffffff;
}
@media (prefers-color-scheme: light) {
.tsb-18 {
--color-tsb18-bg: #eef1f8;
--color-tsb18-surf: #ffffff;
--color-tsb18-glass: oklch(100% 0 0 / 0.68);
--color-tsb18-line: #d3d9e8;
--color-tsb18-ink: #101527;
--color-tsb18-mut: #565f7a;
--color-tsb18-acc: #0a6f5c;
--color-tsb18-acc: oklch(46% 0.1 172);
--color-tsb18-accsoft: #d3ece6;
--color-tsb18-onacc: #ffffff;
}
.tsb-18:has(.tsb-18-theme-input:checked) {
--color-tsb18-bg: #070c1a;
--color-tsb18-surf: #0e1730;
--color-tsb18-glass: oklch(25% 0.05 265 / 0.62);
--color-tsb18-line: #1f2c4d;
--color-tsb18-ink: #e8ecfa;
--color-tsb18-mut: #8e9bc0;
--color-tsb18-acc: #6ff2d0;
--color-tsb18-acc: oklch(88% 0.13 172);
--color-tsb18-accsoft: #10332f;
--color-tsb18-onacc: #070c1a;
}
}
@media (prefers-color-scheme: dark) {
.tsb-18:has(.tsb-18-theme-input:checked) {
--color-tsb18-bg: #eef1f8;
--color-tsb18-surf: #ffffff;
--color-tsb18-glass: oklch(100% 0 0 / 0.68);
--color-tsb18-line: #d3d9e8;
--color-tsb18-ink: #101527;
--color-tsb18-mut: #565f7a;
--color-tsb18-acc: #0a6f5c;
--color-tsb18-acc: oklch(46% 0.1 172);
--color-tsb18-accsoft: #d3ece6;
--color-tsb18-onacc: #ffffff;
}
}<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=Barlow:wght@400;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=Barlow:wght@400;600;700&display=swap">What changed in the port
Which parts became utilities, which stayed CSS, and why.
isolateis one utility that replaces a paragraph of CSS commentary. In the class list it sits next torelative, which is exactly where a reader is asking “what is this positioned against”.- The z-order is three small numbers inside an isolated context —
z-20,z-30,z-40. The port makes the locality visible: there is no reason to reach forz-[9999]when the scale only competes with itself. pointer-events-none/pointer-events-autoon the layer and panel is the same trick the CSS version uses, and in utilities the pair is two lines apart instead of two rules apart.backdrop-blur-[14px] backdrop-saturate-150is a real utility pair; Tailwind emits the-webkit-prefix, so the manual duplicate in the CSS version disappears.- The card grid uses parent-level
[&>article]:and[&_p]:utilities, and the one highlighted card carries!border-tsb18-acc— an important modifier, needed because it overrides a parent-set utility of equal specificity. max-r32:staticon both the layer and the panel is the entire mobile fallback: a floating overlay becomes a normal block, no media-query block required.
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: Pure Tailwind Floating Sidebar Stacking and Overlay Order
Source: https://codefronts.com/navigation/tailwind-css-sidebars/pure-tailwind-floating-sidebar-stacking-and-overlay-order/
A detached, glassy panel floating over the content — and the reason it is a machinery demo rather than a looks demo is isolate. The scene declares itself a stacking context on purpose, so the panel's z- values are resolved locally and cannot be outranked by something unrelated elsewhere on the page. The whole thing is utilities, including the blur.
## HTML
```html
<section class="tsb-18 block relative w-full min-h-svh bg-tsb18-bg text-tsb18-ink font-tsb18-sans leading-[1.55]" aria-label="Nova stage">
<div class="absolute top-3.5 right-3.5 z-90">
<input class="tsb-18-theme-input peer absolute inset-0 w-full h-full m-0 opacity-0 cursor-pointer" type="checkbox" id="tsb-18-theme">
<label class="grid place-items-center w-11 h-11 rounded-[0.9rem] border border-tsb18-line bg-tsb18-surf text-tsb18-ink cursor-pointer peer-focus-visible:outline-2 peer-focus-visible:outline-tsb18-acc peer-focus-visible:outline-offset-2" for="tsb-18-theme">
<svg class="w-4.5 h-4.5" viewBox="0 0 24 24" aria-hidden="true" focusable="false"><circle cx="12" cy="12" r="8.5" fill="none" stroke="currentColor" stroke-width="1.6"/><path d="M12 3.5a8.5 8.5 0 0 0 0 17Z" fill="currentColor"/></svg>
<span class="absolute w-px h-px overflow-hidden whitespace-nowrap [clip-path:inset(50%)]">Toggle dark theme</span>
</label>
</div>
<div class="relative isolate overflow-hidden min-h-svh p-5 bg-tsb18-surf r46:p-8">
<div class="min-w-0 pr-16 r46:pr-68 max-r32:pr-0" id="tsb-18-lib">
<p class="m-0 mb-3.5 font-tsb18-display text-[0.78rem] tracking-[0.16em] uppercase text-tsb18-mut">Continue watching</p>
<div class="grid grid-cols-[repeat(auto-fill,minmax(8.5rem,1fr))] gap-3 [&>article]:min-w-0 [&>article]:aspect-[3/4] [&>article]:flex [&>article]:flex-col [&>article]:justify-end [&>article]:gap-0.5 [&>article]:p-2.5 [&>article]:rounded-[0.8rem] [&>article]:bg-tsb18-bg [&>article]:border [&>article]:border-tsb18-line [&_p]:m-0 [&_p]:min-w-0 [&_p]:text-[0.88rem] [&_p]:font-semibold [&_span]:text-[0.74rem] [&_span]:text-tsb18-mut">
<article class="!border-tsb18-acc"><p>Harbour Wall</p><span>ep 4</span></article>
<article><p>Field Recordings</p><span>ep 11</span></article>
<article><p>Slack Water</p><span>ep 2</span></article>
<article><p>Kestrel</p><span>ep 7</span></article>
<article><p>Two Bells</p><span>ep 1</span></article>
<article><p>Low Tide</p><span>ep 9</span></article>
</div>
</div>
<div class="absolute inset-0 z-20 pointer-events-none max-r32:static">
<div class="absolute inset-0 z-30 bg-[oklch(14%_0.03_260/0.28)] max-r32:hidden" aria-hidden="true"></div>
<nav class="absolute z-40 inset-y-6 right-6 w-[min(14.5rem,62%)] pointer-events-auto flex flex-col p-3 rounded-2xl border border-tsb18-line bg-tsb18-glass backdrop-blur-[14px] backdrop-saturate-150 shadow-[0_1.2rem_2.6rem_oklch(10%_0.02_260/0.45)] max-r32:static max-r32:w-full max-r32:mt-4" aria-label="Nova library">
<p class="m-0 mb-2.5 font-tsb18-display text-[0.7rem] tracking-[0.18em] uppercase text-tsb18-mut">Library</p>
<ul class="list-none m-0 p-0 grid gap-0.5">
<li><a class="flex items-center min-w-0 min-h-11 px-2.5 py-2 rounded-[0.7rem] text-[0.88rem] text-tsb18-ink no-underline hover:bg-tsb18-accsoft focus-visible:outline-2 focus-visible:outline-tsb18-acc focus-visible:outline-offset-2 aria-[current=page]:bg-tsb18-acc aria-[current=page]:text-tsb18-onacc aria-[current=page]:font-semibold" href="#tsb-18-lib" aria-current="page">Continue watching</a></li>
<li><a class="flex items-center min-w-0 min-h-11 px-2.5 py-2 rounded-[0.7rem] text-[0.88rem] text-tsb18-ink no-underline hover:bg-tsb18-accsoft focus-visible:outline-2 focus-visible:outline-tsb18-acc focus-visible:outline-offset-2" href="#tsb-18-lib">My list</a></li>
<li><a class="flex items-center min-w-0 min-h-11 px-2.5 py-2 rounded-[0.7rem] text-[0.88rem] text-tsb18-ink no-underline hover:bg-tsb18-accsoft focus-visible:outline-2 focus-visible:outline-tsb18-acc focus-visible:outline-offset-2" href="#tsb-18-lib">Downloads</a></li>
<li><a class="flex items-center min-w-0 min-h-11 px-2.5 py-2 rounded-[0.7rem] text-[0.88rem] text-tsb18-ink no-underline hover:bg-tsb18-accsoft focus-visible:outline-2 focus-visible:outline-tsb18-acc focus-visible:outline-offset-2" href="#tsb-18-lib">Channels</a></li>
<li><a class="flex items-center min-w-0 min-h-11 px-2.5 py-2 rounded-[0.7rem] text-[0.88rem] text-tsb18-ink no-underline hover:bg-tsb18-accsoft focus-visible:outline-2 focus-visible:outline-tsb18-acc focus-visible:outline-offset-2" href="#tsb-18-lib">Settings</a></li>
</ul>
</nav>
</div>
</div>
</section>
```
## CSS
```css
@import "tailwindcss";
@theme {
--color-tsb18-bg: #070c1a;
--color-tsb18-bg: oklch(13% 0.03 265);
--color-tsb18-surf: #0e1730;
--color-tsb18-surf: oklch(19% 0.04 265);
--color-tsb18-glass: rgba(20, 32, 64, 0.62);
--color-tsb18-glass: oklch(25% 0.05 265 / 0.62);
--color-tsb18-line: #1f2c4d;
--color-tsb18-line: oklch(28% 0.045 265);
--color-tsb18-ink: #e8ecfa;
--color-tsb18-ink: oklch(93% 0.015 265);
--color-tsb18-mut: #8e9bc0;
--color-tsb18-mut: oklch(67% 0.035 265);
--color-tsb18-acc: #6ff2d0;
--color-tsb18-acc: oklch(88% 0.13 172);
--color-tsb18-accsoft: #10332f;
--color-tsb18-accsoft: oklch(28% 0.05 172);
--color-tsb18-onacc: #070c1a;
--color-tsb18-onacc: oklch(13% 0.03 265);
--font-tsb18-sans: system-ui, -apple-system, 'Segoe UI', sans-serif;
--font-tsb18-display: 'Barlow', 'Helvetica Neue', Helvetica, Arial, sans-serif;
--breakpoint-r32: 32rem;
--breakpoint-r46: 46rem;
}
/* Root rule: the full-bleed contract, stated in CSS as well as in the markup's
w-full min-h-svh. */
.tsb-18 {
width: 100%;
min-height: 100svh;
}
.tsb-18 *,
.tsb-18 *::before,
.tsb-18 *::after {
box-sizing: border-box;
}
/* Dark-first demo: the @theme block IS the dark palette, light mirror below. The glass
token carries its own alpha, because backdrop-blur alone is not glass. */
.tsb-18:has(.tsb-18-theme-input:checked) {
--color-tsb18-bg: #eef1f8;
--color-tsb18-surf: #ffffff;
--color-tsb18-glass: oklch(100% 0 0 / 0.68);
--color-tsb18-line: #d3d9e8;
--color-tsb18-ink: #101527;
--color-tsb18-mut: #565f7a;
--color-tsb18-acc: #0a6f5c;
--color-tsb18-acc: oklch(46% 0.1 172);
--color-tsb18-accsoft: #d3ece6;
--color-tsb18-onacc: #ffffff;
}
@media (prefers-color-scheme: light) {
.tsb-18 {
--color-tsb18-bg: #eef1f8;
--color-tsb18-surf: #ffffff;
--color-tsb18-glass: oklch(100% 0 0 / 0.68);
--color-tsb18-line: #d3d9e8;
--color-tsb18-ink: #101527;
--color-tsb18-mut: #565f7a;
--color-tsb18-acc: #0a6f5c;
--color-tsb18-acc: oklch(46% 0.1 172);
--color-tsb18-accsoft: #d3ece6;
--color-tsb18-onacc: #ffffff;
}
.tsb-18:has(.tsb-18-theme-input:checked) {
--color-tsb18-bg: #070c1a;
--color-tsb18-surf: #0e1730;
--color-tsb18-glass: oklch(25% 0.05 265 / 0.62);
--color-tsb18-line: #1f2c4d;
--color-tsb18-ink: #e8ecfa;
--color-tsb18-mut: #8e9bc0;
--color-tsb18-acc: #6ff2d0;
--color-tsb18-acc: oklch(88% 0.13 172);
--color-tsb18-accsoft: #10332f;
--color-tsb18-onacc: #070c1a;
}
}
@media (prefers-color-scheme: dark) {
.tsb-18:has(.tsb-18-theme-input:checked) {
--color-tsb18-bg: #eef1f8;
--color-tsb18-surf: #ffffff;
--color-tsb18-glass: oklch(100% 0 0 / 0.68);
--color-tsb18-line: #d3d9e8;
--color-tsb18-ink: #101527;
--color-tsb18-mut: #565f7a;
--color-tsb18-acc: #0a6f5c;
--color-tsb18-acc: oklch(46% 0.1 172);
--color-tsb18-accsoft: #d3ece6;
--color-tsb18-onacc: #ffffff;
}
}
```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: Pure Tailwind Floating Sidebar Stacking and Overlay Order
Source: https://codefronts.com/navigation/tailwind-css-sidebars/pure-tailwind-floating-sidebar-stacking-and-overlay-order/
A detached, glassy panel floating over the content — and the reason it is a machinery demo rather than a looks demo is isolate. The scene declares itself a stacking context on purpose, so the panel's z- values are resolved locally and cannot be outranked by something unrelated elsewhere on the page. The whole thing is utilities, including the blur.
## HTML
```html
<section class="tsb-18 block relative w-full min-h-svh bg-tsb18-bg text-tsb18-ink font-tsb18-sans leading-[1.55]" aria-label="Nova stage">
<div class="absolute top-3.5 right-3.5 z-90">
<input class="tsb-18-theme-input peer absolute inset-0 w-full h-full m-0 opacity-0 cursor-pointer" type="checkbox" id="tsb-18-theme">
<label class="grid place-items-center w-11 h-11 rounded-[0.9rem] border border-tsb18-line bg-tsb18-surf text-tsb18-ink cursor-pointer peer-focus-visible:outline-2 peer-focus-visible:outline-tsb18-acc peer-focus-visible:outline-offset-2" for="tsb-18-theme">
<svg class="w-4.5 h-4.5" viewBox="0 0 24 24" aria-hidden="true" focusable="false"><circle cx="12" cy="12" r="8.5" fill="none" stroke="currentColor" stroke-width="1.6"/><path d="M12 3.5a8.5 8.5 0 0 0 0 17Z" fill="currentColor"/></svg>
<span class="absolute w-px h-px overflow-hidden whitespace-nowrap [clip-path:inset(50%)]">Toggle dark theme</span>
</label>
</div>
<div class="relative isolate overflow-hidden min-h-svh p-5 bg-tsb18-surf r46:p-8">
<div class="min-w-0 pr-16 r46:pr-68 max-r32:pr-0" id="tsb-18-lib">
<p class="m-0 mb-3.5 font-tsb18-display text-[0.78rem] tracking-[0.16em] uppercase text-tsb18-mut">Continue watching</p>
<div class="grid grid-cols-[repeat(auto-fill,minmax(8.5rem,1fr))] gap-3 [&>article]:min-w-0 [&>article]:aspect-[3/4] [&>article]:flex [&>article]:flex-col [&>article]:justify-end [&>article]:gap-0.5 [&>article]:p-2.5 [&>article]:rounded-[0.8rem] [&>article]:bg-tsb18-bg [&>article]:border [&>article]:border-tsb18-line [&_p]:m-0 [&_p]:min-w-0 [&_p]:text-[0.88rem] [&_p]:font-semibold [&_span]:text-[0.74rem] [&_span]:text-tsb18-mut">
<article class="!border-tsb18-acc"><p>Harbour Wall</p><span>ep 4</span></article>
<article><p>Field Recordings</p><span>ep 11</span></article>
<article><p>Slack Water</p><span>ep 2</span></article>
<article><p>Kestrel</p><span>ep 7</span></article>
<article><p>Two Bells</p><span>ep 1</span></article>
<article><p>Low Tide</p><span>ep 9</span></article>
</div>
</div>
<div class="absolute inset-0 z-20 pointer-events-none max-r32:static">
<div class="absolute inset-0 z-30 bg-[oklch(14%_0.03_260/0.28)] max-r32:hidden" aria-hidden="true"></div>
<nav class="absolute z-40 inset-y-6 right-6 w-[min(14.5rem,62%)] pointer-events-auto flex flex-col p-3 rounded-2xl border border-tsb18-line bg-tsb18-glass backdrop-blur-[14px] backdrop-saturate-150 shadow-[0_1.2rem_2.6rem_oklch(10%_0.02_260/0.45)] max-r32:static max-r32:w-full max-r32:mt-4" aria-label="Nova library">
<p class="m-0 mb-2.5 font-tsb18-display text-[0.7rem] tracking-[0.18em] uppercase text-tsb18-mut">Library</p>
<ul class="list-none m-0 p-0 grid gap-0.5">
<li><a class="flex items-center min-w-0 min-h-11 px-2.5 py-2 rounded-[0.7rem] text-[0.88rem] text-tsb18-ink no-underline hover:bg-tsb18-accsoft focus-visible:outline-2 focus-visible:outline-tsb18-acc focus-visible:outline-offset-2 aria-[current=page]:bg-tsb18-acc aria-[current=page]:text-tsb18-onacc aria-[current=page]:font-semibold" href="#tsb-18-lib" aria-current="page">Continue watching</a></li>
<li><a class="flex items-center min-w-0 min-h-11 px-2.5 py-2 rounded-[0.7rem] text-[0.88rem] text-tsb18-ink no-underline hover:bg-tsb18-accsoft focus-visible:outline-2 focus-visible:outline-tsb18-acc focus-visible:outline-offset-2" href="#tsb-18-lib">My list</a></li>
<li><a class="flex items-center min-w-0 min-h-11 px-2.5 py-2 rounded-[0.7rem] text-[0.88rem] text-tsb18-ink no-underline hover:bg-tsb18-accsoft focus-visible:outline-2 focus-visible:outline-tsb18-acc focus-visible:outline-offset-2" href="#tsb-18-lib">Downloads</a></li>
<li><a class="flex items-center min-w-0 min-h-11 px-2.5 py-2 rounded-[0.7rem] text-[0.88rem] text-tsb18-ink no-underline hover:bg-tsb18-accsoft focus-visible:outline-2 focus-visible:outline-tsb18-acc focus-visible:outline-offset-2" href="#tsb-18-lib">Channels</a></li>
<li><a class="flex items-center min-w-0 min-h-11 px-2.5 py-2 rounded-[0.7rem] text-[0.88rem] text-tsb18-ink no-underline hover:bg-tsb18-accsoft focus-visible:outline-2 focus-visible:outline-tsb18-acc focus-visible:outline-offset-2" href="#tsb-18-lib">Settings</a></li>
</ul>
</nav>
</div>
</div>
</section>
```
## CSS
```css
@import "tailwindcss";
@theme {
--color-tsb18-bg: #070c1a;
--color-tsb18-bg: oklch(13% 0.03 265);
--color-tsb18-surf: #0e1730;
--color-tsb18-surf: oklch(19% 0.04 265);
--color-tsb18-glass: rgba(20, 32, 64, 0.62);
--color-tsb18-glass: oklch(25% 0.05 265 / 0.62);
--color-tsb18-line: #1f2c4d;
--color-tsb18-line: oklch(28% 0.045 265);
--color-tsb18-ink: #e8ecfa;
--color-tsb18-ink: oklch(93% 0.015 265);
--color-tsb18-mut: #8e9bc0;
--color-tsb18-mut: oklch(67% 0.035 265);
--color-tsb18-acc: #6ff2d0;
--color-tsb18-acc: oklch(88% 0.13 172);
--color-tsb18-accsoft: #10332f;
--color-tsb18-accsoft: oklch(28% 0.05 172);
--color-tsb18-onacc: #070c1a;
--color-tsb18-onacc: oklch(13% 0.03 265);
--font-tsb18-sans: system-ui, -apple-system, 'Segoe UI', sans-serif;
--font-tsb18-display: 'Barlow', 'Helvetica Neue', Helvetica, Arial, sans-serif;
--breakpoint-r32: 32rem;
--breakpoint-r46: 46rem;
}
/* Root rule: the full-bleed contract, stated in CSS as well as in the markup's
w-full min-h-svh. */
.tsb-18 {
width: 100%;
min-height: 100svh;
}
.tsb-18 *,
.tsb-18 *::before,
.tsb-18 *::after {
box-sizing: border-box;
}
/* Dark-first demo: the @theme block IS the dark palette, light mirror below. The glass
token carries its own alpha, because backdrop-blur alone is not glass. */
.tsb-18:has(.tsb-18-theme-input:checked) {
--color-tsb18-bg: #eef1f8;
--color-tsb18-surf: #ffffff;
--color-tsb18-glass: oklch(100% 0 0 / 0.68);
--color-tsb18-line: #d3d9e8;
--color-tsb18-ink: #101527;
--color-tsb18-mut: #565f7a;
--color-tsb18-acc: #0a6f5c;
--color-tsb18-acc: oklch(46% 0.1 172);
--color-tsb18-accsoft: #d3ece6;
--color-tsb18-onacc: #ffffff;
}
@media (prefers-color-scheme: light) {
.tsb-18 {
--color-tsb18-bg: #eef1f8;
--color-tsb18-surf: #ffffff;
--color-tsb18-glass: oklch(100% 0 0 / 0.68);
--color-tsb18-line: #d3d9e8;
--color-tsb18-ink: #101527;
--color-tsb18-mut: #565f7a;
--color-tsb18-acc: #0a6f5c;
--color-tsb18-acc: oklch(46% 0.1 172);
--color-tsb18-accsoft: #d3ece6;
--color-tsb18-onacc: #ffffff;
}
.tsb-18:has(.tsb-18-theme-input:checked) {
--color-tsb18-bg: #070c1a;
--color-tsb18-surf: #0e1730;
--color-tsb18-glass: oklch(25% 0.05 265 / 0.62);
--color-tsb18-line: #1f2c4d;
--color-tsb18-ink: #e8ecfa;
--color-tsb18-mut: #8e9bc0;
--color-tsb18-acc: #6ff2d0;
--color-tsb18-acc: oklch(88% 0.13 172);
--color-tsb18-accsoft: #10332f;
--color-tsb18-onacc: #070c1a;
}
}
@media (prefers-color-scheme: dark) {
.tsb-18:has(.tsb-18-theme-input:checked) {
--color-tsb18-bg: #eef1f8;
--color-tsb18-surf: #ffffff;
--color-tsb18-glass: oklch(100% 0 0 / 0.68);
--color-tsb18-line: #d3d9e8;
--color-tsb18-ink: #101527;
--color-tsb18-mut: #565f7a;
--color-tsb18-acc: #0a6f5c;
--color-tsb18-acc: oklch(46% 0.1 172);
--color-tsb18-accsoft: #d3ece6;
--color-tsb18-onacc: #ffffff;
}
}
```How this works
isolate is the point of the demo. Without it, the panel's z-40 competes with every other z-index in the document, and any ancestor that later gains a transform, filter or will-change silently creates a context that reorders everything. One utility makes the scene the root of its own z-order:
<div class="relative isolate overflow-hidden">
<div class="absolute inset-0 z-20 pointer-events-none">
<div class="absolute inset-0 z-30 bg-…" aria-hidden="true"></div>
<nav class="absolute z-40 pointer-events-auto backdrop-blur-[14px]">The pointer-events pair is what makes a tinting overlay usable. The layer covers everything, so it must not receive clicks; the panel inside it must. Two utilities, and the cards behind stay interactive.
Glass needs a background too. backdrop-blur blurs what is BEHIND the element; without a semi-transparent background the blur has nothing to sit under and the panel reads as transparent noise. The token carries the alpha.
On a phone the overlay stops overlaying. max-r32:static turns the layer and the panel into ordinary blocks — a floating panel over a 360px screen covers the content it is meant to navigate.
Make it yours
- Move the panel to the left edge: swap
right-6forleft-6and adjust the content'spr-*reserve. - Change the glass strength with
backdrop-blur-[14px]and the alpha inside--color-tsb18-glass. - Drop the backdrop tint entirely by deleting that one
<div>; the z-order still works. - Retheme through
--color-tsb18-acc; this demo is dark-first and the light mirror is in the stylesheet. - Reserve a different gutter for the panel with the content's
r46:pr-68. - For a real app, add the focus and inert machinery from demo 03 — a floating panel that overlaps content is a dialog in everything but name.
Gotchas — read before shipping
- A
transform,filter,will-changeorbackdrop-filteron an ancestor creates a stacking context whether you wanted one or not.isolateis how you choose instead of discovering it. pointer-events-noneon the layer is required, or the transparent overlay eats every click on the content beneath.backdrop-blurwith no background colour looks broken, not glassy. The alpha is doing half the work.- Escalating z-index values (
z-[9999]) is the symptom of a missing stacking context, not a fix. overflow-hiddenon the scene clips the panel's shadow at the edges — intended here, because the scene is the app frame.- Blur is expensive to composite. One glass surface per screen is fine; a stack of them is a scroll-performance bug.
Browser support
| Chrome | Safari | Firefox | Edge |
|---|---|---|---|
| 111+ | 16.4+ | 128+ | 111+ |
isolation and z-index have no meaningful floor; backdrop-filter is Baseline 2024 in unprefixed form and Tailwind emits the -webkit- pair. Engines without it fall back to the semi-transparent background, which still reads correctly.