07 / 28
All 28 in 28 Tailwind Hamburger Menus
- 01Tailwind Hamburger Menu with Clip-Path Circle Expansion
- 02Tailwind Keyboard Navigable Hamburger Menu with ARIA Attributes
- 03Tailwind Animated 3-Line to X Hamburger Icon Toggle
- 04Tailwind Slide-In Off-Canvas Drawer with Dimmed Backdrop Overlay
- 05Pure Tailwind Checkbox Hack Hamburger Navigation (No JavaScript)
- 06Tailwind Responsive Hamburger Menu with Integrated Search Bar & Social Links
- 07Tailwind Glassmorphism Backdrop Blur Hamburger Navigation
- 08Tailwind Push Page Navigation Menu (Off-Canvas Content Shift)
- 09Pure Tailwind Hamburger Menu Without JavaScript
- 10Tailwind Hamburger Menu Morphing to Close Icon Animation
- 11Tailwind Full Screen Mobile Navigation Overlay
- 12Tailwind Slide Out Sidebar Navigation / Off Canvas Menu
- 13Tailwind Responsive Navbar Mobile Hamburger Toggle Breakpoints
- 14Tailwind Minimalist Floating Hamburger Button
- 15Tailwind CSS Responsive Hamburger Menu Component
- 16Tailwind Rebuild of the Bootstrap 5 Navbar Hamburger Toggle
- 17Tailwind WCAG Accessible Hamburger Menu Example
- 18Pure Tailwind Dropdown Slide Down Mobile Hamburger Menu
- 19Simple 3-Line Tailwind Hamburger Icon Hover Effect
- 20Tailwind Full Screen Blur Overlay Hamburger Menu
- 21Tailwind Mobile Bottom Navigation Bar with Floating Hamburger Toggle
- 22Pure Tailwind Multi-Level Accordion Hamburger Dropdown Menu
- 23Flexbox Navbar Right-Aligned Tailwind Hamburger Icon
- 24Radial Ripple Expand Tailwind Hamburger Menu
- 25Sticky Tailwind Navbar Shrinking Hamburger Icon on Scroll
- 26Neumorphic Tailwind Hamburger Toggle Button
- 27Brutalist Design Bordered Tailwind Hamburger Menu
- 28Tailwind 3D Flip Canvas Mobile Hamburger Navigation
Tailwind Glassmorphism Backdrop Blur Hamburger Navigation
Real frosted glass, not grey-with-opacity — and Tailwind happens to have the exact utilities for it: backdrop-blur-[18px] backdrop-saturate-[1.7] compose into one backdrop-filter, no prefix juggling, no stacking order to remember. The stage runs drifting gradient blobs so you can see the glass working, and the mandatory @supports not fallback stays in CSS, where it belongs.
Untitled UI Pro: 5,000+ React + Tailwind CSS v4 components · from $349 one-time
Untitled UI React · Affiliate link
The code
<section class="thb-07 w-full min-h-svh grid justify-center content-start bg-thb07-bg font-thb07-sans text-thb07-ink px-5 py-9" aria-label="Glassmorphism backdrop blur menu demo">
<div class="group relative isolate w-[min(400px,88vw)] h-135 rounded-3xl overflow-hidden bg-thb07-bg border border-thb07-edge">
<i class="absolute z-0 -left-20 top-15 w-75 h-75 rounded-full blur-[70px] bg-thb07-blob1 animate-[thb07-drift_11s_ease-in-out_infinite_alternate] motion-reduce:animate-none" aria-hidden="true"></i>
<i class="absolute z-0 -right-17.5 -bottom-10 w-65 h-65 rounded-full blur-[70px] bg-thb07-blob2 animate-[thb07-drift_13s_ease-in-out_infinite_alternate-reverse] motion-reduce:animate-none" aria-hidden="true"></i>
<header class="relative z-3 flex items-center justify-between h-18 px-5.5">
<span class="text-[17px] font-bold tracking-[0.22em] uppercase">lumen</span>
<button type="button" aria-expanded="false" aria-controls="thb07-menu" aria-label="Open menu" class="grid place-items-center w-11.5 h-11.5 rounded-[14px] border border-[oklch(1_0_0/0.28)] bg-[oklch(0.97_0.01_260/0.1)] backdrop-blur-[12px] backdrop-saturate-[1.6] text-thb07-ink cursor-pointer transition-[background,scale] duration-250 hover:bg-[oklch(0.97_0.01_260/0.2)] hover:scale-105 active:scale-95 focus-visible:outline-2 focus-visible:outline-thb07-acc focus-visible:outline-offset-3">
<span class="relative block w-4.5 h-3" aria-hidden="true">
<i class="absolute left-0 top-0 w-4.5 h-0.5 rounded-sm bg-current transition-[translate,rotate] duration-300 group-data-open:translate-y-[5px] group-data-open:rotate-45 motion-reduce:transition-none"></i>
<i class="absolute left-0 top-[5px] w-4.5 h-0.5 rounded-sm bg-current transition-[opacity] duration-200 group-data-open:opacity-0 motion-reduce:transition-none"></i>
<i class="absolute left-0 top-2.5 w-4.5 h-0.5 rounded-sm bg-current transition-[translate,rotate] duration-300 group-data-open:-translate-y-[5px] group-data-open:-rotate-45 motion-reduce:transition-none"></i>
</span>
</button>
</header>
<div class="relative z-1 grid justify-items-start gap-3.5 px-6.5 py-11.5" aria-hidden="true">
<h2 class="text-[37px] leading-[1.05] font-bold tracking-[-0.03em] text-balance">Light, refracted.</h2>
<p class="max-w-[26ch] text-sm leading-relaxed text-thb07-mut text-pretty">Studio for luminous interfaces — glass, gradients and grain.</p>
<div class="mt-2.5 px-4 py-2.25 rounded-full border border-[oklch(1_0_0/0.25)] bg-[oklch(0.97_0.01_260/0.08)] backdrop-blur-[8px] text-[11.5px] font-semibold tracking-[0.12em] uppercase">Scroll ↓</div>
</div>
<nav id="thb07-menu" aria-label="Site" class="thb07-glass absolute z-2 inset-x-4 top-21.5 bottom-4 flex flex-col justify-center gap-0.5 px-6.5 rounded-[20px] bg-[oklch(0.97_0.01_260/0.12)] backdrop-blur-[18px] backdrop-saturate-[1.7] border border-[oklch(1_0_0/0.28)] shadow-[inset_0_1px_0_oklch(1_0_0/0.25),0_24px_48px_-20px_oklch(0.2_0.05_280/0.5)] opacity-0 -translate-y-3.5 scale-[0.98] invisible [transition:opacity_.35s,translate_.4s_var(--ease-thb07),scale_.4s_var(--ease-thb07),visibility_0s_.4s] group-data-open:opacity-100 group-data-open:translate-y-0 group-data-open:scale-100 group-data-open:visible group-data-open:[transition:opacity_.35s,translate_.4s_var(--ease-thb07),scale_.4s_var(--ease-thb07),visibility_0s_0s]">
<a href="#work" style="--i:0" class="group/l flex items-center justify-between py-3.75 px-0.5 rounded-md border-b border-[oklch(1_0_0/0.14)] text-[28px] font-bold tracking-[-0.02em] text-thb07-ink no-underline opacity-0 translate-y-3 transition-[color,opacity,translate] duration-350 ease-thb07 hover:text-thb07-acc focus-visible:text-thb07-acc focus-visible:outline-2 focus-visible:outline-thb07-acc focus-visible:outline-offset-4 group-data-open:opacity-100 group-data-open:translate-y-0 group-data-open:[transition-delay:calc(100ms+var(--i)*55ms)] motion-reduce:translate-y-0 motion-reduce:duration-150"><span>Work</span><span class="text-base opacity-0 -translate-x-1.5 translate-y-1 transition-[opacity,translate] duration-250 group-hover/l:opacity-100 group-hover/l:translate-x-0 group-hover/l:translate-y-0 group-focus-visible/l:opacity-100 group-focus-visible/l:translate-x-0 group-focus-visible/l:translate-y-0" aria-hidden="true">↗</span></a>
<a href="#services" style="--i:1" class="group/l flex items-center justify-between py-3.75 px-0.5 rounded-md border-b border-[oklch(1_0_0/0.14)] text-[28px] font-bold tracking-[-0.02em] text-thb07-ink no-underline opacity-0 translate-y-3 transition-[color,opacity,translate] duration-350 ease-thb07 hover:text-thb07-acc focus-visible:text-thb07-acc focus-visible:outline-2 focus-visible:outline-thb07-acc focus-visible:outline-offset-4 group-data-open:opacity-100 group-data-open:translate-y-0 group-data-open:[transition-delay:calc(100ms+var(--i)*55ms)] motion-reduce:translate-y-0 motion-reduce:duration-150"><span>Services</span><span class="text-base opacity-0 -translate-x-1.5 translate-y-1 transition-[opacity,translate] duration-250 group-hover/l:opacity-100 group-hover/l:translate-x-0 group-hover/l:translate-y-0 group-focus-visible/l:opacity-100 group-focus-visible/l:translate-x-0 group-focus-visible/l:translate-y-0" aria-hidden="true">↗</span></a>
<a href="#about" style="--i:2" class="group/l flex items-center justify-between py-3.75 px-0.5 rounded-md border-b border-[oklch(1_0_0/0.14)] text-[28px] font-bold tracking-[-0.02em] text-thb07-ink no-underline opacity-0 translate-y-3 transition-[color,opacity,translate] duration-350 ease-thb07 hover:text-thb07-acc focus-visible:text-thb07-acc focus-visible:outline-2 focus-visible:outline-thb07-acc focus-visible:outline-offset-4 group-data-open:opacity-100 group-data-open:translate-y-0 group-data-open:[transition-delay:calc(100ms+var(--i)*55ms)] motion-reduce:translate-y-0 motion-reduce:duration-150"><span>About</span><span class="text-base opacity-0 -translate-x-1.5 translate-y-1 transition-[opacity,translate] duration-250 group-hover/l:opacity-100 group-hover/l:translate-x-0 group-hover/l:translate-y-0 group-focus-visible/l:opacity-100 group-focus-visible/l:translate-x-0 group-focus-visible/l:translate-y-0" aria-hidden="true">↗</span></a>
<a href="#contact" style="--i:3" class="group/l flex items-center justify-between py-3.75 px-0.5 rounded-md border-b border-[oklch(1_0_0/0.14)] text-[28px] font-bold tracking-[-0.02em] text-thb07-ink no-underline opacity-0 translate-y-3 transition-[color,opacity,translate] duration-350 ease-thb07 hover:text-thb07-acc focus-visible:text-thb07-acc focus-visible:outline-2 focus-visible:outline-thb07-acc focus-visible:outline-offset-4 group-data-open:opacity-100 group-data-open:translate-y-0 group-data-open:[transition-delay:calc(100ms+var(--i)*55ms)] motion-reduce:translate-y-0 motion-reduce:duration-150"><span>Contact</span><span class="text-base opacity-0 -translate-x-1.5 translate-y-1 transition-[opacity,translate] duration-250 group-hover/l:opacity-100 group-hover/l:translate-x-0 group-hover/l:translate-y-0 group-focus-visible/l:opacity-100 group-focus-visible/l:translate-x-0 group-focus-visible/l:translate-y-0" aria-hidden="true">↗</span></a>
<footer style="--i:4" class="flex items-center justify-between mt-5.5 text-xs text-thb07-mut opacity-0 translate-y-3 transition-[opacity,translate] duration-350 ease-thb07 group-data-open:opacity-100 group-data-open:translate-y-0 group-data-open:[transition-delay:calc(100ms+var(--i)*55ms)] motion-reduce:translate-y-0 motion-reduce:duration-150">
<span>© 2026 lumen</span>
<a href="#privacy" class="text-xs text-thb07-mut no-underline transition-[color] duration-200 hover:text-thb07-acc focus-visible:text-thb07-acc focus-visible:outline-2 focus-visible:outline-thb07-acc focus-visible:outline-offset-2">Privacy</a>
</footer>
</nav>
</div>
</section><section class="thb-07 w-full min-h-svh grid justify-center content-start bg-thb07-bg font-thb07-sans text-thb07-ink px-5 py-9" aria-label="Glassmorphism backdrop blur menu demo">
<div class="group relative isolate w-[min(400px,88vw)] h-135 rounded-3xl overflow-hidden bg-thb07-bg border border-thb07-edge">
<i class="absolute z-0 -left-20 top-15 w-75 h-75 rounded-full blur-[70px] bg-thb07-blob1 animate-[thb07-drift_11s_ease-in-out_infinite_alternate] motion-reduce:animate-none" aria-hidden="true"></i>
<i class="absolute z-0 -right-17.5 -bottom-10 w-65 h-65 rounded-full blur-[70px] bg-thb07-blob2 animate-[thb07-drift_13s_ease-in-out_infinite_alternate-reverse] motion-reduce:animate-none" aria-hidden="true"></i>
<header class="relative z-3 flex items-center justify-between h-18 px-5.5">
<span class="text-[17px] font-bold tracking-[0.22em] uppercase">lumen</span>
<button type="button" aria-expanded="false" aria-controls="thb07-menu" aria-label="Open menu" class="grid place-items-center w-11.5 h-11.5 rounded-[14px] border border-[oklch(1_0_0/0.28)] bg-[oklch(0.97_0.01_260/0.1)] backdrop-blur-[12px] backdrop-saturate-[1.6] text-thb07-ink cursor-pointer transition-[background,scale] duration-250 hover:bg-[oklch(0.97_0.01_260/0.2)] hover:scale-105 active:scale-95 focus-visible:outline-2 focus-visible:outline-thb07-acc focus-visible:outline-offset-3">
<span class="relative block w-4.5 h-3" aria-hidden="true">
<i class="absolute left-0 top-0 w-4.5 h-0.5 rounded-sm bg-current transition-[translate,rotate] duration-300 group-data-open:translate-y-[5px] group-data-open:rotate-45 motion-reduce:transition-none"></i>
<i class="absolute left-0 top-[5px] w-4.5 h-0.5 rounded-sm bg-current transition-[opacity] duration-200 group-data-open:opacity-0 motion-reduce:transition-none"></i>
<i class="absolute left-0 top-2.5 w-4.5 h-0.5 rounded-sm bg-current transition-[translate,rotate] duration-300 group-data-open:-translate-y-[5px] group-data-open:-rotate-45 motion-reduce:transition-none"></i>
</span>
</button>
</header>
<div class="relative z-1 grid justify-items-start gap-3.5 px-6.5 py-11.5" aria-hidden="true">
<h2 class="text-[37px] leading-[1.05] font-bold tracking-[-0.03em] text-balance">Light, refracted.</h2>
<p class="max-w-[26ch] text-sm leading-relaxed text-thb07-mut text-pretty">Studio for luminous interfaces — glass, gradients and grain.</p>
<div class="mt-2.5 px-4 py-2.25 rounded-full border border-[oklch(1_0_0/0.25)] bg-[oklch(0.97_0.01_260/0.08)] backdrop-blur-[8px] text-[11.5px] font-semibold tracking-[0.12em] uppercase">Scroll ↓</div>
</div>
<nav id="thb07-menu" aria-label="Site" class="thb07-glass absolute z-2 inset-x-4 top-21.5 bottom-4 flex flex-col justify-center gap-0.5 px-6.5 rounded-[20px] bg-[oklch(0.97_0.01_260/0.12)] backdrop-blur-[18px] backdrop-saturate-[1.7] border border-[oklch(1_0_0/0.28)] shadow-[inset_0_1px_0_oklch(1_0_0/0.25),0_24px_48px_-20px_oklch(0.2_0.05_280/0.5)] opacity-0 -translate-y-3.5 scale-[0.98] invisible [transition:opacity_.35s,translate_.4s_var(--ease-thb07),scale_.4s_var(--ease-thb07),visibility_0s_.4s] group-data-open:opacity-100 group-data-open:translate-y-0 group-data-open:scale-100 group-data-open:visible group-data-open:[transition:opacity_.35s,translate_.4s_var(--ease-thb07),scale_.4s_var(--ease-thb07),visibility_0s_0s]">
<a href="#work" style="--i:0" class="group/l flex items-center justify-between py-3.75 px-0.5 rounded-md border-b border-[oklch(1_0_0/0.14)] text-[28px] font-bold tracking-[-0.02em] text-thb07-ink no-underline opacity-0 translate-y-3 transition-[color,opacity,translate] duration-350 ease-thb07 hover:text-thb07-acc focus-visible:text-thb07-acc focus-visible:outline-2 focus-visible:outline-thb07-acc focus-visible:outline-offset-4 group-data-open:opacity-100 group-data-open:translate-y-0 group-data-open:[transition-delay:calc(100ms+var(--i)*55ms)] motion-reduce:translate-y-0 motion-reduce:duration-150"><span>Work</span><span class="text-base opacity-0 -translate-x-1.5 translate-y-1 transition-[opacity,translate] duration-250 group-hover/l:opacity-100 group-hover/l:translate-x-0 group-hover/l:translate-y-0 group-focus-visible/l:opacity-100 group-focus-visible/l:translate-x-0 group-focus-visible/l:translate-y-0" aria-hidden="true">↗</span></a>
<a href="#services" style="--i:1" class="group/l flex items-center justify-between py-3.75 px-0.5 rounded-md border-b border-[oklch(1_0_0/0.14)] text-[28px] font-bold tracking-[-0.02em] text-thb07-ink no-underline opacity-0 translate-y-3 transition-[color,opacity,translate] duration-350 ease-thb07 hover:text-thb07-acc focus-visible:text-thb07-acc focus-visible:outline-2 focus-visible:outline-thb07-acc focus-visible:outline-offset-4 group-data-open:opacity-100 group-data-open:translate-y-0 group-data-open:[transition-delay:calc(100ms+var(--i)*55ms)] motion-reduce:translate-y-0 motion-reduce:duration-150"><span>Services</span><span class="text-base opacity-0 -translate-x-1.5 translate-y-1 transition-[opacity,translate] duration-250 group-hover/l:opacity-100 group-hover/l:translate-x-0 group-hover/l:translate-y-0 group-focus-visible/l:opacity-100 group-focus-visible/l:translate-x-0 group-focus-visible/l:translate-y-0" aria-hidden="true">↗</span></a>
<a href="#about" style="--i:2" class="group/l flex items-center justify-between py-3.75 px-0.5 rounded-md border-b border-[oklch(1_0_0/0.14)] text-[28px] font-bold tracking-[-0.02em] text-thb07-ink no-underline opacity-0 translate-y-3 transition-[color,opacity,translate] duration-350 ease-thb07 hover:text-thb07-acc focus-visible:text-thb07-acc focus-visible:outline-2 focus-visible:outline-thb07-acc focus-visible:outline-offset-4 group-data-open:opacity-100 group-data-open:translate-y-0 group-data-open:[transition-delay:calc(100ms+var(--i)*55ms)] motion-reduce:translate-y-0 motion-reduce:duration-150"><span>About</span><span class="text-base opacity-0 -translate-x-1.5 translate-y-1 transition-[opacity,translate] duration-250 group-hover/l:opacity-100 group-hover/l:translate-x-0 group-hover/l:translate-y-0 group-focus-visible/l:opacity-100 group-focus-visible/l:translate-x-0 group-focus-visible/l:translate-y-0" aria-hidden="true">↗</span></a>
<a href="#contact" style="--i:3" class="group/l flex items-center justify-between py-3.75 px-0.5 rounded-md border-b border-[oklch(1_0_0/0.14)] text-[28px] font-bold tracking-[-0.02em] text-thb07-ink no-underline opacity-0 translate-y-3 transition-[color,opacity,translate] duration-350 ease-thb07 hover:text-thb07-acc focus-visible:text-thb07-acc focus-visible:outline-2 focus-visible:outline-thb07-acc focus-visible:outline-offset-4 group-data-open:opacity-100 group-data-open:translate-y-0 group-data-open:[transition-delay:calc(100ms+var(--i)*55ms)] motion-reduce:translate-y-0 motion-reduce:duration-150"><span>Contact</span><span class="text-base opacity-0 -translate-x-1.5 translate-y-1 transition-[opacity,translate] duration-250 group-hover/l:opacity-100 group-hover/l:translate-x-0 group-hover/l:translate-y-0 group-focus-visible/l:opacity-100 group-focus-visible/l:translate-x-0 group-focus-visible/l:translate-y-0" aria-hidden="true">↗</span></a>
<footer style="--i:4" class="flex items-center justify-between mt-5.5 text-xs text-thb07-mut opacity-0 translate-y-3 transition-[opacity,translate] duration-350 ease-thb07 group-data-open:opacity-100 group-data-open:translate-y-0 group-data-open:[transition-delay:calc(100ms+var(--i)*55ms)] motion-reduce:translate-y-0 motion-reduce:duration-150">
<span>© 2026 lumen</span>
<a href="#privacy" class="text-xs text-thb07-mut no-underline transition-[color] duration-200 hover:text-thb07-acc focus-visible:text-thb07-acc focus-visible:outline-2 focus-visible:outline-thb07-acc focus-visible:outline-offset-2">Privacy</a>
</footer>
</nav>
</div>
</section>@import "tailwindcss";
@theme {
--color-thb07-bg: #322a4d;
--color-thb07-bg: oklch(0.22 0.045 285);
--color-thb07-edge: #55496f;
--color-thb07-edge: oklch(0.35 0.05 285);
--color-thb07-ink: #f6f4fb;
--color-thb07-ink: oklch(0.97 0.008 285);
--color-thb07-mut: #c3bcd4;
--color-thb07-mut: oklch(0.78 0.03 285);
--color-thb07-acc: #6fd7e0;
--color-thb07-acc: oklch(0.82 0.14 190);
--color-thb07-blob1: #a03fd8;
--color-thb07-blob1: oklch(0.62 0.23 310);
--color-thb07-blob2: #4bc0d8;
--color-thb07-blob2: oklch(0.75 0.16 200);
--font-thb07-sans: 'Space Grotesk', system-ui, sans-serif;
--font-thb07-mono: 'JetBrains Mono', ui-monospace, monospace;
--ease-thb07: cubic-bezier(0.2, 0.7, 0.2, 1);
}
/* Keyframes are a rule, not a value — no utility form exists. */
@keyframes thb07-drift {
from {
translate: 0 0;
scale: 1;
}
to {
translate: 40px -30px;
scale: 1.15;
}
}
/* The one thing that MUST stay a feature query: without it, an engine with no
backdrop-filter paints a 12%-alpha panel and page text crashes through the links. */
@supports not (backdrop-filter: blur(1px)) {
.thb-07 .thb07-glass {
background: oklch(0.25 0.04 280 / 0.94);
}
.thb-07 button[aria-controls="thb07-menu"] {
background: oklch(0.3 0.05 280 / 0.85);
}
}
/* Root rule: the full-bleed contract, stated in CSS as well as in the markup's
w-full min-h-svh. It scopes the demo, and it holds the stage at full height in the
moment before the browser build has compiled its utilities. */
.thb-07 {
width: 100%;
min-height: 100svh;
}@import "tailwindcss";
@theme {
--color-thb07-bg: #322a4d;
--color-thb07-bg: oklch(0.22 0.045 285);
--color-thb07-edge: #55496f;
--color-thb07-edge: oklch(0.35 0.05 285);
--color-thb07-ink: #f6f4fb;
--color-thb07-ink: oklch(0.97 0.008 285);
--color-thb07-mut: #c3bcd4;
--color-thb07-mut: oklch(0.78 0.03 285);
--color-thb07-acc: #6fd7e0;
--color-thb07-acc: oklch(0.82 0.14 190);
--color-thb07-blob1: #a03fd8;
--color-thb07-blob1: oklch(0.62 0.23 310);
--color-thb07-blob2: #4bc0d8;
--color-thb07-blob2: oklch(0.75 0.16 200);
--font-thb07-sans: 'Space Grotesk', system-ui, sans-serif;
--font-thb07-mono: 'JetBrains Mono', ui-monospace, monospace;
--ease-thb07: cubic-bezier(0.2, 0.7, 0.2, 1);
}
/* Keyframes are a rule, not a value — no utility form exists. */
@keyframes thb07-drift {
from {
translate: 0 0;
scale: 1;
}
to {
translate: 40px -30px;
scale: 1.15;
}
}
/* The one thing that MUST stay a feature query: without it, an engine with no
backdrop-filter paints a 12%-alpha panel and page text crashes through the links. */
@supports not (backdrop-filter: blur(1px)) {
.thb-07 .thb07-glass {
background: oklch(0.25 0.04 280 / 0.94);
}
.thb-07 button[aria-controls="thb07-menu"] {
background: oklch(0.3 0.05 280 / 0.85);
}
}
/* Root rule: the full-bleed contract, stated in CSS as well as in the markup's
w-full min-h-svh. It scopes the demo, and it holds the stage at full height in the
moment before the browser build has compiled its utilities. */
.thb-07 {
width: 100%;
min-height: 100svh;
}(function () {
document.querySelectorAll('.thb-07 > .group').forEach(function (stage) {
if (stage.dataset.bound) return; stage.dataset.bound = '1';
var btn = stage.querySelector('button[aria-controls="thb07-menu"]');
function set(open) {
stage.toggleAttribute('data-open', open);
btn.setAttribute('aria-expanded', String(open));
btn.setAttribute('aria-label', open ? 'Close menu' : 'Open menu');
}
btn.addEventListener('click', function () { set(btn.getAttribute('aria-expanded') !== 'true'); });
stage.addEventListener('keydown', function (e) {
if (e.key === 'Escape' && stage.hasAttribute('data-open')) { set(false); btn.focus(); }
});
});
})();(function () {
document.querySelectorAll('.thb-07 > .group').forEach(function (stage) {
if (stage.dataset.bound) return; stage.dataset.bound = '1';
var btn = stage.querySelector('button[aria-controls="thb07-menu"]');
function set(open) {
stage.toggleAttribute('data-open', open);
btn.setAttribute('aria-expanded', String(open));
btn.setAttribute('aria-label', open ? 'Close menu' : 'Open menu');
}
btn.addEventListener('click', function () { set(btn.getAttribute('aria-expanded') !== 'true'); });
stage.addEventListener('keydown', function (e) {
if (e.key === 'Escape' && stage.hasAttribute('data-open')) { set(false); btn.focus(); }
});
});
})();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-thb07-bg: #322a4d;
--color-thb07-bg: oklch(0.22 0.045 285);
--color-thb07-edge: #55496f;
--color-thb07-edge: oklch(0.35 0.05 285);
--color-thb07-ink: #f6f4fb;
--color-thb07-ink: oklch(0.97 0.008 285);
--color-thb07-mut: #c3bcd4;
--color-thb07-mut: oklch(0.78 0.03 285);
--color-thb07-acc: #6fd7e0;
--color-thb07-acc: oklch(0.82 0.14 190);
--color-thb07-blob1: #a03fd8;
--color-thb07-blob1: oklch(0.62 0.23 310);
--color-thb07-blob2: #4bc0d8;
--color-thb07-blob2: oklch(0.75 0.16 200);
--font-thb07-sans: 'Space Grotesk', system-ui, sans-serif;
--font-thb07-mono: 'JetBrains Mono', ui-monospace, monospace;
--ease-thb07: cubic-bezier(0.2, 0.7, 0.2, 1);
}
/* Keyframes are a rule, not a value — no utility form exists. */
@keyframes thb07-drift {
from {
translate: 0 0;
scale: 1;
}
to {
translate: 40px -30px;
scale: 1.15;
}
}
/* The one thing that MUST stay a feature query: without it, an engine with no
backdrop-filter paints a 12%-alpha panel and page text crashes through the links. */
@supports not (backdrop-filter: blur(1px)) {
.thb-07 .thb07-glass {
background: oklch(0.25 0.04 280 / 0.94);
}
.thb-07 button[aria-controls="thb07-menu"] {
background: oklch(0.3 0.05 280 / 0.85);
}
}
/* Root rule: the full-bleed contract, stated in CSS as well as in the markup's
w-full min-h-svh. It scopes the demo, and it holds the stage at full height in the
moment before the browser build has compiled its utilities. */
.thb-07 {
width: 100%;
min-height: 100svh;
}@import "tailwindcss";
@theme {
--color-thb07-bg: #322a4d;
--color-thb07-bg: oklch(0.22 0.045 285);
--color-thb07-edge: #55496f;
--color-thb07-edge: oklch(0.35 0.05 285);
--color-thb07-ink: #f6f4fb;
--color-thb07-ink: oklch(0.97 0.008 285);
--color-thb07-mut: #c3bcd4;
--color-thb07-mut: oklch(0.78 0.03 285);
--color-thb07-acc: #6fd7e0;
--color-thb07-acc: oklch(0.82 0.14 190);
--color-thb07-blob1: #a03fd8;
--color-thb07-blob1: oklch(0.62 0.23 310);
--color-thb07-blob2: #4bc0d8;
--color-thb07-blob2: oklch(0.75 0.16 200);
--font-thb07-sans: 'Space Grotesk', system-ui, sans-serif;
--font-thb07-mono: 'JetBrains Mono', ui-monospace, monospace;
--ease-thb07: cubic-bezier(0.2, 0.7, 0.2, 1);
}
/* Keyframes are a rule, not a value — no utility form exists. */
@keyframes thb07-drift {
from {
translate: 0 0;
scale: 1;
}
to {
translate: 40px -30px;
scale: 1.15;
}
}
/* The one thing that MUST stay a feature query: without it, an engine with no
backdrop-filter paints a 12%-alpha panel and page text crashes through the links. */
@supports not (backdrop-filter: blur(1px)) {
.thb-07 .thb07-glass {
background: oklch(0.25 0.04 280 / 0.94);
}
.thb-07 button[aria-controls="thb07-menu"] {
background: oklch(0.3 0.05 280 / 0.85);
}
}
/* Root rule: the full-bleed contract, stated in CSS as well as in the markup's
w-full min-h-svh. It scopes the demo, and it holds the stage at full height in the
moment before the browser build has compiled its utilities. */
.thb-07 {
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&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=Space+Grotesk:wght@400;500;600;700&family=JetBrains+Mono:wght@400;500;600&display=swap">What changed in the port
Which parts became utilities, which stayed CSS, and why.
- The glass recipe is the port's happiest case:
backdrop-blur-*andbackdrop-saturate-*COMPOSE into onebackdrop-filter, and Tailwind emits the-webkit-prefix, so the two lines the CSS version has to keep in sync become two independent utilities. - The prefixed duplicate declaration disappears entirely — that is four lines of the original stylesheet gone with no loss of Safari support.
- The
::afterarrow on each link becomes a real<span aria-hidden>driven by a named group (group/l). Tailwind could doafter:content-['…'], but a span is inspectable and cannot double an announcement. - The
@keyframesdrift and the@supports notfallback both stay in CSS. Keyframes are a rule, and a feature query touching two selectors is clearer than two longsupports-*arbitrary variants. - The blobs'
animationshorthand rides in one arbitraryanimate-[…]value, andmotion-reduce:animate-nonestops the loop dead rather than slowing it. isolateon the stage replaces the CSS version'sisolation:isolaterule with a real utility — needed so the blurred blobs cannot bleed across demos on the collection page.
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 Glassmorphism Backdrop Blur Hamburger Navigation
Source: https://codefronts.com/navigation/tailwind-hamburger-menus/tailwind-glassmorphism-backdrop-blur-hamburger-navigation/
Real frosted glass, not grey-with-opacity — and Tailwind happens to have the exact utilities for it: backdrop-blur-[18px] backdrop-saturate-[1.7] compose into one backdrop-filter, no prefix juggling, no stacking order to remember. The stage runs drifting gradient blobs so you can see the glass working, and the mandatory @supports not fallback stays in CSS, where it belongs.
## HTML
```html
<section class="thb-07 w-full min-h-svh grid justify-center content-start bg-thb07-bg font-thb07-sans text-thb07-ink px-5 py-9" aria-label="Glassmorphism backdrop blur menu demo">
<div class="group relative isolate w-[min(400px,88vw)] h-135 rounded-3xl overflow-hidden bg-thb07-bg border border-thb07-edge">
<i class="absolute z-0 -left-20 top-15 w-75 h-75 rounded-full blur-[70px] bg-thb07-blob1 animate-[thb07-drift_11s_ease-in-out_infinite_alternate] motion-reduce:animate-none" aria-hidden="true"></i>
<i class="absolute z-0 -right-17.5 -bottom-10 w-65 h-65 rounded-full blur-[70px] bg-thb07-blob2 animate-[thb07-drift_13s_ease-in-out_infinite_alternate-reverse] motion-reduce:animate-none" aria-hidden="true"></i>
<header class="relative z-3 flex items-center justify-between h-18 px-5.5">
<span class="text-[17px] font-bold tracking-[0.22em] uppercase">lumen</span>
<button type="button" aria-expanded="false" aria-controls="thb07-menu" aria-label="Open menu" class="grid place-items-center w-11.5 h-11.5 rounded-[14px] border border-[oklch(1_0_0/0.28)] bg-[oklch(0.97_0.01_260/0.1)] backdrop-blur-[12px] backdrop-saturate-[1.6] text-thb07-ink cursor-pointer transition-[background,scale] duration-250 hover:bg-[oklch(0.97_0.01_260/0.2)] hover:scale-105 active:scale-95 focus-visible:outline-2 focus-visible:outline-thb07-acc focus-visible:outline-offset-3">
<span class="relative block w-4.5 h-3" aria-hidden="true">
<i class="absolute left-0 top-0 w-4.5 h-0.5 rounded-sm bg-current transition-[translate,rotate] duration-300 group-data-open:translate-y-[5px] group-data-open:rotate-45 motion-reduce:transition-none"></i>
<i class="absolute left-0 top-[5px] w-4.5 h-0.5 rounded-sm bg-current transition-[opacity] duration-200 group-data-open:opacity-0 motion-reduce:transition-none"></i>
<i class="absolute left-0 top-2.5 w-4.5 h-0.5 rounded-sm bg-current transition-[translate,rotate] duration-300 group-data-open:-translate-y-[5px] group-data-open:-rotate-45 motion-reduce:transition-none"></i>
</span>
</button>
</header>
<div class="relative z-1 grid justify-items-start gap-3.5 px-6.5 py-11.5" aria-hidden="true">
<h2 class="text-[37px] leading-[1.05] font-bold tracking-[-0.03em] text-balance">Light, refracted.</h2>
<p class="max-w-[26ch] text-sm leading-relaxed text-thb07-mut text-pretty">Studio for luminous interfaces — glass, gradients and grain.</p>
<div class="mt-2.5 px-4 py-2.25 rounded-full border border-[oklch(1_0_0/0.25)] bg-[oklch(0.97_0.01_260/0.08)] backdrop-blur-[8px] text-[11.5px] font-semibold tracking-[0.12em] uppercase">Scroll ↓</div>
</div>
<nav id="thb07-menu" aria-label="Site" class="thb07-glass absolute z-2 inset-x-4 top-21.5 bottom-4 flex flex-col justify-center gap-0.5 px-6.5 rounded-[20px] bg-[oklch(0.97_0.01_260/0.12)] backdrop-blur-[18px] backdrop-saturate-[1.7] border border-[oklch(1_0_0/0.28)] shadow-[inset_0_1px_0_oklch(1_0_0/0.25),0_24px_48px_-20px_oklch(0.2_0.05_280/0.5)] opacity-0 -translate-y-3.5 scale-[0.98] invisible [transition:opacity_.35s,translate_.4s_var(--ease-thb07),scale_.4s_var(--ease-thb07),visibility_0s_.4s] group-data-open:opacity-100 group-data-open:translate-y-0 group-data-open:scale-100 group-data-open:visible group-data-open:[transition:opacity_.35s,translate_.4s_var(--ease-thb07),scale_.4s_var(--ease-thb07),visibility_0s_0s]">
<a href="#work" style="--i:0" class="group/l flex items-center justify-between py-3.75 px-0.5 rounded-md border-b border-[oklch(1_0_0/0.14)] text-[28px] font-bold tracking-[-0.02em] text-thb07-ink no-underline opacity-0 translate-y-3 transition-[color,opacity,translate] duration-350 ease-thb07 hover:text-thb07-acc focus-visible:text-thb07-acc focus-visible:outline-2 focus-visible:outline-thb07-acc focus-visible:outline-offset-4 group-data-open:opacity-100 group-data-open:translate-y-0 group-data-open:[transition-delay:calc(100ms+var(--i)*55ms)] motion-reduce:translate-y-0 motion-reduce:duration-150"><span>Work</span><span class="text-base opacity-0 -translate-x-1.5 translate-y-1 transition-[opacity,translate] duration-250 group-hover/l:opacity-100 group-hover/l:translate-x-0 group-hover/l:translate-y-0 group-focus-visible/l:opacity-100 group-focus-visible/l:translate-x-0 group-focus-visible/l:translate-y-0" aria-hidden="true">↗</span></a>
<a href="#services" style="--i:1" class="group/l flex items-center justify-between py-3.75 px-0.5 rounded-md border-b border-[oklch(1_0_0/0.14)] text-[28px] font-bold tracking-[-0.02em] text-thb07-ink no-underline opacity-0 translate-y-3 transition-[color,opacity,translate] duration-350 ease-thb07 hover:text-thb07-acc focus-visible:text-thb07-acc focus-visible:outline-2 focus-visible:outline-thb07-acc focus-visible:outline-offset-4 group-data-open:opacity-100 group-data-open:translate-y-0 group-data-open:[transition-delay:calc(100ms+var(--i)*55ms)] motion-reduce:translate-y-0 motion-reduce:duration-150"><span>Services</span><span class="text-base opacity-0 -translate-x-1.5 translate-y-1 transition-[opacity,translate] duration-250 group-hover/l:opacity-100 group-hover/l:translate-x-0 group-hover/l:translate-y-0 group-focus-visible/l:opacity-100 group-focus-visible/l:translate-x-0 group-focus-visible/l:translate-y-0" aria-hidden="true">↗</span></a>
<a href="#about" style="--i:2" class="group/l flex items-center justify-between py-3.75 px-0.5 rounded-md border-b border-[oklch(1_0_0/0.14)] text-[28px] font-bold tracking-[-0.02em] text-thb07-ink no-underline opacity-0 translate-y-3 transition-[color,opacity,translate] duration-350 ease-thb07 hover:text-thb07-acc focus-visible:text-thb07-acc focus-visible:outline-2 focus-visible:outline-thb07-acc focus-visible:outline-offset-4 group-data-open:opacity-100 group-data-open:translate-y-0 group-data-open:[transition-delay:calc(100ms+var(--i)*55ms)] motion-reduce:translate-y-0 motion-reduce:duration-150"><span>About</span><span class="text-base opacity-0 -translate-x-1.5 translate-y-1 transition-[opacity,translate] duration-250 group-hover/l:opacity-100 group-hover/l:translate-x-0 group-hover/l:translate-y-0 group-focus-visible/l:opacity-100 group-focus-visible/l:translate-x-0 group-focus-visible/l:translate-y-0" aria-hidden="true">↗</span></a>
<a href="#contact" style="--i:3" class="group/l flex items-center justify-between py-3.75 px-0.5 rounded-md border-b border-[oklch(1_0_0/0.14)] text-[28px] font-bold tracking-[-0.02em] text-thb07-ink no-underline opacity-0 translate-y-3 transition-[color,opacity,translate] duration-350 ease-thb07 hover:text-thb07-acc focus-visible:text-thb07-acc focus-visible:outline-2 focus-visible:outline-thb07-acc focus-visible:outline-offset-4 group-data-open:opacity-100 group-data-open:translate-y-0 group-data-open:[transition-delay:calc(100ms+var(--i)*55ms)] motion-reduce:translate-y-0 motion-reduce:duration-150"><span>Contact</span><span class="text-base opacity-0 -translate-x-1.5 translate-y-1 transition-[opacity,translate] duration-250 group-hover/l:opacity-100 group-hover/l:translate-x-0 group-hover/l:translate-y-0 group-focus-visible/l:opacity-100 group-focus-visible/l:translate-x-0 group-focus-visible/l:translate-y-0" aria-hidden="true">↗</span></a>
<footer style="--i:4" class="flex items-center justify-between mt-5.5 text-xs text-thb07-mut opacity-0 translate-y-3 transition-[opacity,translate] duration-350 ease-thb07 group-data-open:opacity-100 group-data-open:translate-y-0 group-data-open:[transition-delay:calc(100ms+var(--i)*55ms)] motion-reduce:translate-y-0 motion-reduce:duration-150">
<span>© 2026 lumen</span>
<a href="#privacy" class="text-xs text-thb07-mut no-underline transition-[color] duration-200 hover:text-thb07-acc focus-visible:text-thb07-acc focus-visible:outline-2 focus-visible:outline-thb07-acc focus-visible:outline-offset-2">Privacy</a>
</footer>
</nav>
</div>
</section>
```
## CSS
```css
@import "tailwindcss";
@theme {
--color-thb07-bg: #322a4d;
--color-thb07-bg: oklch(0.22 0.045 285);
--color-thb07-edge: #55496f;
--color-thb07-edge: oklch(0.35 0.05 285);
--color-thb07-ink: #f6f4fb;
--color-thb07-ink: oklch(0.97 0.008 285);
--color-thb07-mut: #c3bcd4;
--color-thb07-mut: oklch(0.78 0.03 285);
--color-thb07-acc: #6fd7e0;
--color-thb07-acc: oklch(0.82 0.14 190);
--color-thb07-blob1: #a03fd8;
--color-thb07-blob1: oklch(0.62 0.23 310);
--color-thb07-blob2: #4bc0d8;
--color-thb07-blob2: oklch(0.75 0.16 200);
--font-thb07-sans: 'Space Grotesk', system-ui, sans-serif;
--font-thb07-mono: 'JetBrains Mono', ui-monospace, monospace;
--ease-thb07: cubic-bezier(0.2, 0.7, 0.2, 1);
}
/* Keyframes are a rule, not a value — no utility form exists. */
@keyframes thb07-drift {
from {
translate: 0 0;
scale: 1;
}
to {
translate: 40px -30px;
scale: 1.15;
}
}
/* The one thing that MUST stay a feature query: without it, an engine with no
backdrop-filter paints a 12%-alpha panel and page text crashes through the links. */
@supports not (backdrop-filter: blur(1px)) {
.thb-07 .thb07-glass {
background: oklch(0.25 0.04 280 / 0.94);
}
.thb-07 button[aria-controls="thb07-menu"] {
background: oklch(0.3 0.05 280 / 0.85);
}
}
/* Root rule: the full-bleed contract, stated in CSS as well as in the markup's
w-full min-h-svh. It scopes the demo, and it holds the stage at full height in the
moment before the browser build has compiled its utilities. */
.thb-07 {
width: 100%;
min-height: 100svh;
}
```
## JavaScript
```js
(function () {
document.querySelectorAll('.thb-07 > .group').forEach(function (stage) {
if (stage.dataset.bound) return; stage.dataset.bound = '1';
var btn = stage.querySelector('button[aria-controls="thb07-menu"]');
function set(open) {
stage.toggleAttribute('data-open', open);
btn.setAttribute('aria-expanded', String(open));
btn.setAttribute('aria-label', open ? 'Close menu' : 'Open menu');
}
btn.addEventListener('click', function () { set(btn.getAttribute('aria-expanded') !== 'true'); });
stage.addEventListener('keydown', function (e) {
if (e.key === 'Escape' && stage.hasAttribute('data-open')) { set(false); btn.focus(); }
});
});
})();
```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 Glassmorphism Backdrop Blur Hamburger Navigation
Source: https://codefronts.com/navigation/tailwind-hamburger-menus/tailwind-glassmorphism-backdrop-blur-hamburger-navigation/
Real frosted glass, not grey-with-opacity — and Tailwind happens to have the exact utilities for it: backdrop-blur-[18px] backdrop-saturate-[1.7] compose into one backdrop-filter, no prefix juggling, no stacking order to remember. The stage runs drifting gradient blobs so you can see the glass working, and the mandatory @supports not fallback stays in CSS, where it belongs.
## HTML
```html
<section class="thb-07 w-full min-h-svh grid justify-center content-start bg-thb07-bg font-thb07-sans text-thb07-ink px-5 py-9" aria-label="Glassmorphism backdrop blur menu demo">
<div class="group relative isolate w-[min(400px,88vw)] h-135 rounded-3xl overflow-hidden bg-thb07-bg border border-thb07-edge">
<i class="absolute z-0 -left-20 top-15 w-75 h-75 rounded-full blur-[70px] bg-thb07-blob1 animate-[thb07-drift_11s_ease-in-out_infinite_alternate] motion-reduce:animate-none" aria-hidden="true"></i>
<i class="absolute z-0 -right-17.5 -bottom-10 w-65 h-65 rounded-full blur-[70px] bg-thb07-blob2 animate-[thb07-drift_13s_ease-in-out_infinite_alternate-reverse] motion-reduce:animate-none" aria-hidden="true"></i>
<header class="relative z-3 flex items-center justify-between h-18 px-5.5">
<span class="text-[17px] font-bold tracking-[0.22em] uppercase">lumen</span>
<button type="button" aria-expanded="false" aria-controls="thb07-menu" aria-label="Open menu" class="grid place-items-center w-11.5 h-11.5 rounded-[14px] border border-[oklch(1_0_0/0.28)] bg-[oklch(0.97_0.01_260/0.1)] backdrop-blur-[12px] backdrop-saturate-[1.6] text-thb07-ink cursor-pointer transition-[background,scale] duration-250 hover:bg-[oklch(0.97_0.01_260/0.2)] hover:scale-105 active:scale-95 focus-visible:outline-2 focus-visible:outline-thb07-acc focus-visible:outline-offset-3">
<span class="relative block w-4.5 h-3" aria-hidden="true">
<i class="absolute left-0 top-0 w-4.5 h-0.5 rounded-sm bg-current transition-[translate,rotate] duration-300 group-data-open:translate-y-[5px] group-data-open:rotate-45 motion-reduce:transition-none"></i>
<i class="absolute left-0 top-[5px] w-4.5 h-0.5 rounded-sm bg-current transition-[opacity] duration-200 group-data-open:opacity-0 motion-reduce:transition-none"></i>
<i class="absolute left-0 top-2.5 w-4.5 h-0.5 rounded-sm bg-current transition-[translate,rotate] duration-300 group-data-open:-translate-y-[5px] group-data-open:-rotate-45 motion-reduce:transition-none"></i>
</span>
</button>
</header>
<div class="relative z-1 grid justify-items-start gap-3.5 px-6.5 py-11.5" aria-hidden="true">
<h2 class="text-[37px] leading-[1.05] font-bold tracking-[-0.03em] text-balance">Light, refracted.</h2>
<p class="max-w-[26ch] text-sm leading-relaxed text-thb07-mut text-pretty">Studio for luminous interfaces — glass, gradients and grain.</p>
<div class="mt-2.5 px-4 py-2.25 rounded-full border border-[oklch(1_0_0/0.25)] bg-[oklch(0.97_0.01_260/0.08)] backdrop-blur-[8px] text-[11.5px] font-semibold tracking-[0.12em] uppercase">Scroll ↓</div>
</div>
<nav id="thb07-menu" aria-label="Site" class="thb07-glass absolute z-2 inset-x-4 top-21.5 bottom-4 flex flex-col justify-center gap-0.5 px-6.5 rounded-[20px] bg-[oklch(0.97_0.01_260/0.12)] backdrop-blur-[18px] backdrop-saturate-[1.7] border border-[oklch(1_0_0/0.28)] shadow-[inset_0_1px_0_oklch(1_0_0/0.25),0_24px_48px_-20px_oklch(0.2_0.05_280/0.5)] opacity-0 -translate-y-3.5 scale-[0.98] invisible [transition:opacity_.35s,translate_.4s_var(--ease-thb07),scale_.4s_var(--ease-thb07),visibility_0s_.4s] group-data-open:opacity-100 group-data-open:translate-y-0 group-data-open:scale-100 group-data-open:visible group-data-open:[transition:opacity_.35s,translate_.4s_var(--ease-thb07),scale_.4s_var(--ease-thb07),visibility_0s_0s]">
<a href="#work" style="--i:0" class="group/l flex items-center justify-between py-3.75 px-0.5 rounded-md border-b border-[oklch(1_0_0/0.14)] text-[28px] font-bold tracking-[-0.02em] text-thb07-ink no-underline opacity-0 translate-y-3 transition-[color,opacity,translate] duration-350 ease-thb07 hover:text-thb07-acc focus-visible:text-thb07-acc focus-visible:outline-2 focus-visible:outline-thb07-acc focus-visible:outline-offset-4 group-data-open:opacity-100 group-data-open:translate-y-0 group-data-open:[transition-delay:calc(100ms+var(--i)*55ms)] motion-reduce:translate-y-0 motion-reduce:duration-150"><span>Work</span><span class="text-base opacity-0 -translate-x-1.5 translate-y-1 transition-[opacity,translate] duration-250 group-hover/l:opacity-100 group-hover/l:translate-x-0 group-hover/l:translate-y-0 group-focus-visible/l:opacity-100 group-focus-visible/l:translate-x-0 group-focus-visible/l:translate-y-0" aria-hidden="true">↗</span></a>
<a href="#services" style="--i:1" class="group/l flex items-center justify-between py-3.75 px-0.5 rounded-md border-b border-[oklch(1_0_0/0.14)] text-[28px] font-bold tracking-[-0.02em] text-thb07-ink no-underline opacity-0 translate-y-3 transition-[color,opacity,translate] duration-350 ease-thb07 hover:text-thb07-acc focus-visible:text-thb07-acc focus-visible:outline-2 focus-visible:outline-thb07-acc focus-visible:outline-offset-4 group-data-open:opacity-100 group-data-open:translate-y-0 group-data-open:[transition-delay:calc(100ms+var(--i)*55ms)] motion-reduce:translate-y-0 motion-reduce:duration-150"><span>Services</span><span class="text-base opacity-0 -translate-x-1.5 translate-y-1 transition-[opacity,translate] duration-250 group-hover/l:opacity-100 group-hover/l:translate-x-0 group-hover/l:translate-y-0 group-focus-visible/l:opacity-100 group-focus-visible/l:translate-x-0 group-focus-visible/l:translate-y-0" aria-hidden="true">↗</span></a>
<a href="#about" style="--i:2" class="group/l flex items-center justify-between py-3.75 px-0.5 rounded-md border-b border-[oklch(1_0_0/0.14)] text-[28px] font-bold tracking-[-0.02em] text-thb07-ink no-underline opacity-0 translate-y-3 transition-[color,opacity,translate] duration-350 ease-thb07 hover:text-thb07-acc focus-visible:text-thb07-acc focus-visible:outline-2 focus-visible:outline-thb07-acc focus-visible:outline-offset-4 group-data-open:opacity-100 group-data-open:translate-y-0 group-data-open:[transition-delay:calc(100ms+var(--i)*55ms)] motion-reduce:translate-y-0 motion-reduce:duration-150"><span>About</span><span class="text-base opacity-0 -translate-x-1.5 translate-y-1 transition-[opacity,translate] duration-250 group-hover/l:opacity-100 group-hover/l:translate-x-0 group-hover/l:translate-y-0 group-focus-visible/l:opacity-100 group-focus-visible/l:translate-x-0 group-focus-visible/l:translate-y-0" aria-hidden="true">↗</span></a>
<a href="#contact" style="--i:3" class="group/l flex items-center justify-between py-3.75 px-0.5 rounded-md border-b border-[oklch(1_0_0/0.14)] text-[28px] font-bold tracking-[-0.02em] text-thb07-ink no-underline opacity-0 translate-y-3 transition-[color,opacity,translate] duration-350 ease-thb07 hover:text-thb07-acc focus-visible:text-thb07-acc focus-visible:outline-2 focus-visible:outline-thb07-acc focus-visible:outline-offset-4 group-data-open:opacity-100 group-data-open:translate-y-0 group-data-open:[transition-delay:calc(100ms+var(--i)*55ms)] motion-reduce:translate-y-0 motion-reduce:duration-150"><span>Contact</span><span class="text-base opacity-0 -translate-x-1.5 translate-y-1 transition-[opacity,translate] duration-250 group-hover/l:opacity-100 group-hover/l:translate-x-0 group-hover/l:translate-y-0 group-focus-visible/l:opacity-100 group-focus-visible/l:translate-x-0 group-focus-visible/l:translate-y-0" aria-hidden="true">↗</span></a>
<footer style="--i:4" class="flex items-center justify-between mt-5.5 text-xs text-thb07-mut opacity-0 translate-y-3 transition-[opacity,translate] duration-350 ease-thb07 group-data-open:opacity-100 group-data-open:translate-y-0 group-data-open:[transition-delay:calc(100ms+var(--i)*55ms)] motion-reduce:translate-y-0 motion-reduce:duration-150">
<span>© 2026 lumen</span>
<a href="#privacy" class="text-xs text-thb07-mut no-underline transition-[color] duration-200 hover:text-thb07-acc focus-visible:text-thb07-acc focus-visible:outline-2 focus-visible:outline-thb07-acc focus-visible:outline-offset-2">Privacy</a>
</footer>
</nav>
</div>
</section>
```
## CSS
```css
@import "tailwindcss";
@theme {
--color-thb07-bg: #322a4d;
--color-thb07-bg: oklch(0.22 0.045 285);
--color-thb07-edge: #55496f;
--color-thb07-edge: oklch(0.35 0.05 285);
--color-thb07-ink: #f6f4fb;
--color-thb07-ink: oklch(0.97 0.008 285);
--color-thb07-mut: #c3bcd4;
--color-thb07-mut: oklch(0.78 0.03 285);
--color-thb07-acc: #6fd7e0;
--color-thb07-acc: oklch(0.82 0.14 190);
--color-thb07-blob1: #a03fd8;
--color-thb07-blob1: oklch(0.62 0.23 310);
--color-thb07-blob2: #4bc0d8;
--color-thb07-blob2: oklch(0.75 0.16 200);
--font-thb07-sans: 'Space Grotesk', system-ui, sans-serif;
--font-thb07-mono: 'JetBrains Mono', ui-monospace, monospace;
--ease-thb07: cubic-bezier(0.2, 0.7, 0.2, 1);
}
/* Keyframes are a rule, not a value — no utility form exists. */
@keyframes thb07-drift {
from {
translate: 0 0;
scale: 1;
}
to {
translate: 40px -30px;
scale: 1.15;
}
}
/* The one thing that MUST stay a feature query: without it, an engine with no
backdrop-filter paints a 12%-alpha panel and page text crashes through the links. */
@supports not (backdrop-filter: blur(1px)) {
.thb-07 .thb07-glass {
background: oklch(0.25 0.04 280 / 0.94);
}
.thb-07 button[aria-controls="thb07-menu"] {
background: oklch(0.3 0.05 280 / 0.85);
}
}
/* Root rule: the full-bleed contract, stated in CSS as well as in the markup's
w-full min-h-svh. It scopes the demo, and it holds the stage at full height in the
moment before the browser build has compiled its utilities. */
.thb-07 {
width: 100%;
min-height: 100svh;
}
```
## JavaScript
```js
(function () {
document.querySelectorAll('.thb-07 > .group').forEach(function (stage) {
if (stage.dataset.bound) return; stage.dataset.bound = '1';
var btn = stage.querySelector('button[aria-controls="thb07-menu"]');
function set(open) {
stage.toggleAttribute('data-open', open);
btn.setAttribute('aria-expanded', String(open));
btn.setAttribute('aria-label', open ? 'Close menu' : 'Open menu');
}
btn.addEventListener('click', function () { set(btn.getAttribute('aria-expanded') !== 'true'); });
stage.addEventListener('keydown', function (e) {
if (e.key === 'Escape' && stage.hasAttribute('data-open')) { set(false); btn.focus(); }
});
});
})();
```How this works
The whole material is one class list.
class="bg-[oklch(0.97_0.01_260/0.12)]
backdrop-blur-[18px] backdrop-saturate-[1.7]
border border-[oklch(1_0_0/0.28)]
shadow-[inset_0_1px_0_oklch(1_0_0/0.25),0_24px_48px_-20px_oklch(0.2_0.05_280/0.5)]"Every part earns its place. The background alpha must stay low (8–16%): most “glassmorphism” fails because a 60%-white background hides the blur entirely. backdrop-saturate-[1.7] is the secret ingredient — blur alone reads as fog, while boosting backdrop saturation makes colour bloom through the frost. The white-alpha border fakes glass's bright refracting edge, and the inset highlight sells a top-lit surface.
Composition is the port's win. In hand-written CSS you must remember that backdrop-filter is one property and a second declaration overwrites the first. Tailwind's backdrop-* utilities each set a variable that composes into one filter chain, so blur and saturate can be added, removed or overridden independently — including per breakpoint or per state.
Glass needs something behind it. Two blurred oklch blobs drift on a slow keyframe loop; in production your hero image or brand gradient plays that role. The @keyframes block stays in CSS, because keyframes are a rule, not a value.
The fallback is mandatory. @supports not (backdrop-filter: blur(1px)) raises the panel to 94% alpha. Without it, an engine with no support paints a 12%-alpha sheet with page text crashing straight through the links. Tailwind has a supports-* variant, but a two-selector feature query is cleaner as three lines of CSS than as two long arbitrary variants.
Make it yours
- Frost intensity:
backdrop-blur-[10px]is tinted glass,[18px]frosted,[28px]privacy glass. Keep saturate between 1.4 and 1.9 — beyond that whites go neon. - Dark glass: swap the background for
bg-[oklch(0.2_0.03_280/0.35)]and the border forborder-[oklch(1_0_0/0.14)]. Same physics, moodier panel. - Recolour the blob field through
--color-thb07-blob1/--color-thb07-blob2, or delete both and put a photo behind — the glass does not care. - Add grain, the 2026 finish: an
after:layer with a tiny SVG-noise data URI at 4% opacity kills banding in the blur. - Slow the drift by editing the
11s/13sin the twoanimate-*arbitrary durations.
Gotchas — read before shipping
backdrop-blur-*only samples what is BEHIND the element. On a flat white page the glass is invisible — design the backdrop first.- An ancestor with
filter,transformorwill-changecan flatten the backdrop root and break sampling in Safari. Transforming the glass panel itself (as here) is fine; transforming a wrapper is not. - Blur is per-pixel work. A viewport-sized sheet at
backdrop-blur-[30px]measurably drops frame rate on mid-range Androids — keep glass partial-viewport or lower the radius with a breakpoint variant. - Do not put the
@supports notfallback in an arbitrary variant.supports-*exists, but a feature query touching two selectors is clearer as CSS, and it must raise the alpha or the menu is unreadable. - Tailwind's
backdrop-*utilities compose; a raw[backdrop-filter:…]arbitrary property does not, and will silently clobber anybackdrop-*utility on the same element. isolateon the stage is load-bearing: it keeps the blurred blobs inside the stage's own stacking context so they cannot bleed over neighbouring demos.
Browser support
| Chrome | Safari | Firefox | Edge |
|---|---|---|---|
| 111+ | 16.4+ | 128+ | 111+ |
backdrop-filter is Chrome 76+, Safari 9+ (prefixed — Tailwind emits the prefix for you) and Firefox 103+; the @supports not fallback covers everything older. The floor quoted here is Tailwind v4's own generated sheet.