01 / 11
All 11 in 11 Tailwind CSS Glassmorphic Navbars
- 01Tailwind Glassmorphism Navbar for SaaS Landing Pages
- 02Tailwind Transparent Navbar That Turns Frosted Glass on Scroll
- 03Dark Mode Cyberpunk Neon Glass Navbar in Tailwind CSS
- 04Tailwind Floating Pill Navbar with Glass Effect
- 05Tailwind Glassmorphism Dropdown & Mega Menu Navbar
- 06Tailwind Mobile Hamburger Menu with Glass Off-Canvas Drawer
- 07Lightweight Tailwind Sticky Header with Backdrop Blur (Zero JS)
- 08Tailwind Animated Gradient Border Glass Navbar
- 09Accessible Tailwind Glassmorphism Navbar (WCAG AA)
- 10Next.js Tailwind Glass Header with Framer Motion
- 11Minimalist Tailwind Glass Navbar for Portfolios
Tailwind Glassmorphism Navbar for SaaS Landing Pages
The query everyone types: a floating frosted-glass SaaS header over a vibrant gradient hero — brand, centred links, ghost sign-in and a gradient CTA. The CSS original's glass trio is now bg-white/50 border-white/60 backdrop-blur-lg backdrop-saturate-[1.8], and the links it simply hid on phones now live in a zero-JS Popover API glass menu.
Complete Tailwind CSS landing page templates in HTML, React, Next.js and Vue · from $49
Cruip · Affiliate link
The code
<div class="tgn-01 w-full min-h-svh bg-tgn01-g2 bg-[radial-gradient(120%_120%_at_12%_0%,var(--color-tgn01-g1)_0%,var(--color-tgn01-g2)_40%,var(--color-tgn01-g3)_100%)] font-tgn01-sans">
<div class="relative h-svh overflow-y-auto scroll-smooth p-3 sm:p-5">
<header class="sticky top-3 z-10 flex h-16 items-center gap-4 rounded-2xl border border-white/60 bg-white/50 py-2.5 pr-2.5 pl-4 shadow-[0_8px_30px_-6px_oklch(0.25_0.1_285/0.35)] backdrop-blur-lg backdrop-saturate-[1.8] not-supports-[backdrop-filter:blur(1px)]:bg-white/90 sm:pl-5">
<a class="flex items-center gap-2.5 rounded-lg font-tgn01-display text-lg font-extrabold tracking-[-0.03em] text-tgn01-ink focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-tgn01-ink" href="#"><span aria-hidden="true" class="grid size-8 place-items-center rounded-[10px] bg-linear-to-br from-tgn01-cta1 to-tgn01-cta2 text-xs text-white shadow-[0_4px_12px_-2px_var(--color-tgn01-cta2)]">◆</span>Nimbus</a>
<nav class="mx-auto max-md:hidden" aria-label="Primary">
<ul class="flex gap-1">
<li><a href="#" aria-current="page" class="flex h-11 items-center rounded-xl px-3.5 text-sm font-semibold text-tgn01-ink/80 transition-colors hover:bg-white/55 hover:text-tgn01-ink aria-[current=page]:bg-white/70 aria-[current=page]:text-tgn01-ink focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-tgn01-ink">Product</a></li>
<li><a href="#" class="flex h-11 items-center rounded-xl px-3.5 text-sm font-semibold text-tgn01-ink/80 transition-colors hover:bg-white/55 hover:text-tgn01-ink aria-[current=page]:bg-white/70 aria-[current=page]:text-tgn01-ink focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-tgn01-ink">Pricing</a></li>
<li><a href="#" class="flex h-11 items-center rounded-xl px-3.5 text-sm font-semibold text-tgn01-ink/80 transition-colors hover:bg-white/55 hover:text-tgn01-ink aria-[current=page]:bg-white/70 aria-[current=page]:text-tgn01-ink focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-tgn01-ink">Docs</a></li>
<li><a href="#" class="flex h-11 items-center rounded-xl px-3.5 text-sm font-semibold text-tgn01-ink/80 transition-colors hover:bg-white/55 hover:text-tgn01-ink aria-[current=page]:bg-white/70 aria-[current=page]:text-tgn01-ink focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-tgn01-ink">Blog</a></li>
</ul>
</nav>
<div class="flex items-center gap-1.5 max-md:ml-auto">
<a href="#" class="flex h-11 items-center rounded-xl px-3.5 text-sm font-semibold text-tgn01-ink/80 transition-colors hover:bg-white/55 hover:text-tgn01-ink aria-[current=page]:bg-white/70 aria-[current=page]:text-tgn01-ink focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-tgn01-ink max-sm:hidden">Sign in</a>
<a href="#" class="group flex h-11 items-center gap-1.5 rounded-xl bg-linear-to-br from-tgn01-cta1 to-tgn01-cta2 px-4 text-sm font-bold text-white shadow-[0_8px_20px_-4px_var(--color-tgn01-cta2)] transition-[translate,box-shadow] duration-150 hover:-translate-y-0.5 hover:shadow-[0_12px_26px_-4px_var(--color-tgn01-cta2)] focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-white motion-reduce:transition-none sm:px-5">Start free<span aria-hidden="true" class="transition-transform group-hover:translate-x-0.5">→</span></a>
<button type="button" popovertarget="tgn01-menu" aria-label="Open menu" class="grid size-11 cursor-pointer place-items-center rounded-xl text-tgn01-ink hover:bg-white/55 focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-tgn01-ink md:hidden"><svg class="size-5" viewBox="0 0 20 20" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" aria-hidden="true"><path d="M3 6h14M3 10h14M3 14h14"/></svg></button>
</div>
</header>
<nav id="tgn01-menu" popover aria-label="Mobile primary" class="fixed inset-x-3 top-20 bottom-auto m-0 w-auto rounded-2xl border border-white/70 bg-white/65 p-2 font-tgn01-sans text-tgn01-ink opacity-0 shadow-[0_20px_50px_-12px_oklch(0.25_0.1_285/0.45)] backdrop-blur-xl backdrop-saturate-[1.8] transition-[opacity,translate,overlay,display] transition-discrete duration-200 -translate-y-2 open:translate-y-0 open:opacity-100 starting:open:-translate-y-2 starting:open:opacity-0 motion-reduce:transition-none">
<a href="#" aria-current="page" class="flex h-12 items-center rounded-xl px-4 text-[15px] font-semibold text-tgn01-ink hover:bg-white/60 focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-tgn01-ink">Product</a>
<a href="#" class="flex h-12 items-center rounded-xl px-4 text-[15px] font-semibold text-tgn01-ink hover:bg-white/60 focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-tgn01-ink">Pricing</a>
<a href="#" class="flex h-12 items-center rounded-xl px-4 text-[15px] font-semibold text-tgn01-ink hover:bg-white/60 focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-tgn01-ink">Docs</a>
<a href="#" class="flex h-12 items-center rounded-xl px-4 text-[15px] font-semibold text-tgn01-ink hover:bg-white/60 focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-tgn01-ink">Blog</a>
<a href="#" class="flex h-12 items-center rounded-xl px-4 text-[15px] font-semibold text-tgn01-ink hover:bg-white/60 focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-tgn01-ink mt-1 border-t border-tgn01-ink/10 rounded-t-none">Sign in</a>
</nav>
<div class="max-w-xl px-2 pt-16 pb-6 sm:px-3.5">
<p class="mb-4 inline-flex rounded-full border border-white/40 bg-white/20 px-3 py-1.5 text-xs font-bold tracking-[0.14em] text-white uppercase backdrop-blur-sm">Ship faster</p>
<h2 class="font-tgn01-display text-[clamp(30px,5.4vw,46px)]/[1.04] font-extrabold tracking-[-0.035em] text-balance text-white [text-shadow:0_2px_24px_oklch(0.2_0.1_300/0.3)]">The workspace your whole team ships from.</h2>
</div>
<div class="max-w-2xl px-2 pt-6 pb-20 text-white/95 [text-shadow:0_1px_6px_oklch(0.25_0.1_300/0.35)] sm:px-3.5 [&_p]:mb-3.5 [&_p]:text-[15px]/[1.65] [&_p]:font-medium [&_p]:text-pretty [&_:is(h1,h2,h3)]:text-balance [&_h2]:mt-5 [&_h2]:mb-3.5 [&_h2]:text-[22px]/[1.2] [&_h2]:font-extrabold [&_h2]:tracking-[-0.015em] [&_h3]:mt-8 [&_h3]:mb-3 [&_h3]:text-lg/[1.25] [&_h3]:font-bold [&_h3]:tracking-[-0.01em] [&_:is(h2,h3)]:font-tgn01-display [&_:is(h2,h3)]:text-white [&_code]:rounded-md [&_code]:px-1.5 [&_code]:py-0.5 [&_code]:font-tgn01-mono [&_code]:text-[12.5px] [&_code]:font-medium [&_code]:border [&_code]:border-white/40 [&_code]:bg-white/25 [&_code]:text-white [&_code]:[text-shadow:none]">
<p>The floating glass header stays pinned to the top as you scroll. Translucent white fill + <code>backdrop-filter:blur(16px) saturate(180%)</code> + a 1px hairline — the classic trio.</p>
<p>The <code>saturate(180%)</code> boost is the secret sauce most Tailwind snippets miss. Plain <code>blur()</code> alone looks grey and dead; boosting saturation makes the frosted pane feel like it's actually made of the colours behind it.</p>
<p>Dark link text stays high-contrast even as the gradient shifts underneath, because the fill is white-ish and ≥45% opaque. The blur alone is never enough to guarantee contrast; the fill opacity is the actual floor.</p>
<p>The CTA is a linear-gradient pill with its own coloured shadow so it reads as the single most important control on the page. It lifts on hover with a subtle <code>translateY(-2px)</code>.</p>
<p>For a darker product, flip the fill to <code>rgba(17,17,20,.5)</code> and link colour to near-white — the same structure works as a dark SaaS header without changing a single selector.</p>
<p>Tailwind users: the class equivalent is <code>sticky top-4 backdrop-blur-xl backdrop-saturate-150 bg-white/50 border border-white/60 rounded-2xl shadow-lg</code>. Every declaration maps to a utility class or arbitrary value.</p>
<h3>Why saturate matters more than blur radius</h3>
<p>Increasing the blur radius past 20-24px starts to cost frames on low-end Android hardware. Increasing the saturation stops at zero cost — saturation is a colour matrix operation, not a spatial convolution.</p>
<p>Practical range: <code>blur(12px)</code> at <code>saturate(180%)</code> reads as premium and stays smooth. <code>blur(24px)</code> at <code>saturate(120%)</code> reads as heavy privacy-glass but taxes older devices. Pick the trade-off deliberately.</p>
<p>Test the header over your <em>lightest</em> hero, not your darkest. Dark heroes hide contrast bugs; light heroes reveal them.</p>
<h3>Layout hygiene for sticky glass headers</h3>
<p>The header must have a fixed <code>height</code> declaration (56px in this demo). Sticky elements with intrinsic height can shift as fonts swap in — a real Cumulative Layout Shift hit that Google's Core Web Vitals reports.</p>
<p>Keep the sticky header out of ancestors with <code>overflow:hidden</code> on the block axis. This is the single most common sticky-fails-silently bug — the header renders once at the top and never moves.</p>
<p>Give the containing element a defined block-size (the outer wrapper here is <code>min-height:100vh</code>). Sticky without a resolvable containing block behaves like static.</p>
<p>Above 1200px viewport, consider raising the nav's max-width to keep the CTA anchored to the right edge rather than floating in a wide gap. Below 640px, collapse the primary links into a hamburger and keep the CTA prominent.</p>
<h3>Real SaaS marketing sites shipping this pattern</h3>
<p>Stripe uses a variant with heavier saturation over its animated gradient hero. Linear uses a near-black variant with cyan accent. Vercel uses white glass with brand purple CTA. Superhuman uses navy glass with peach CTA. Framer uses a pill variant of the same recipe (see Demo 04).</p>
<p>Every one of them ships the same three-declaration recipe: translucent fill + <code>backdrop-filter:blur() saturate()</code> + 1px hairline. The palette differs; the structure doesn't.</p>
<p>Keep scrolling — the sticky bar demonstrates its main job by staying pinned as the content flows underneath it.</p>
</div>
</div>
</div><div class="tgn-01 w-full min-h-svh bg-tgn01-g2 bg-[radial-gradient(120%_120%_at_12%_0%,var(--color-tgn01-g1)_0%,var(--color-tgn01-g2)_40%,var(--color-tgn01-g3)_100%)] font-tgn01-sans">
<div class="relative h-svh overflow-y-auto scroll-smooth p-3 sm:p-5">
<header class="sticky top-3 z-10 flex h-16 items-center gap-4 rounded-2xl border border-white/60 bg-white/50 py-2.5 pr-2.5 pl-4 shadow-[0_8px_30px_-6px_oklch(0.25_0.1_285/0.35)] backdrop-blur-lg backdrop-saturate-[1.8] not-supports-[backdrop-filter:blur(1px)]:bg-white/90 sm:pl-5">
<a class="flex items-center gap-2.5 rounded-lg font-tgn01-display text-lg font-extrabold tracking-[-0.03em] text-tgn01-ink focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-tgn01-ink" href="#"><span aria-hidden="true" class="grid size-8 place-items-center rounded-[10px] bg-linear-to-br from-tgn01-cta1 to-tgn01-cta2 text-xs text-white shadow-[0_4px_12px_-2px_var(--color-tgn01-cta2)]">◆</span>Nimbus</a>
<nav class="mx-auto max-md:hidden" aria-label="Primary">
<ul class="flex gap-1">
<li><a href="#" aria-current="page" class="flex h-11 items-center rounded-xl px-3.5 text-sm font-semibold text-tgn01-ink/80 transition-colors hover:bg-white/55 hover:text-tgn01-ink aria-[current=page]:bg-white/70 aria-[current=page]:text-tgn01-ink focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-tgn01-ink">Product</a></li>
<li><a href="#" class="flex h-11 items-center rounded-xl px-3.5 text-sm font-semibold text-tgn01-ink/80 transition-colors hover:bg-white/55 hover:text-tgn01-ink aria-[current=page]:bg-white/70 aria-[current=page]:text-tgn01-ink focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-tgn01-ink">Pricing</a></li>
<li><a href="#" class="flex h-11 items-center rounded-xl px-3.5 text-sm font-semibold text-tgn01-ink/80 transition-colors hover:bg-white/55 hover:text-tgn01-ink aria-[current=page]:bg-white/70 aria-[current=page]:text-tgn01-ink focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-tgn01-ink">Docs</a></li>
<li><a href="#" class="flex h-11 items-center rounded-xl px-3.5 text-sm font-semibold text-tgn01-ink/80 transition-colors hover:bg-white/55 hover:text-tgn01-ink aria-[current=page]:bg-white/70 aria-[current=page]:text-tgn01-ink focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-tgn01-ink">Blog</a></li>
</ul>
</nav>
<div class="flex items-center gap-1.5 max-md:ml-auto">
<a href="#" class="flex h-11 items-center rounded-xl px-3.5 text-sm font-semibold text-tgn01-ink/80 transition-colors hover:bg-white/55 hover:text-tgn01-ink aria-[current=page]:bg-white/70 aria-[current=page]:text-tgn01-ink focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-tgn01-ink max-sm:hidden">Sign in</a>
<a href="#" class="group flex h-11 items-center gap-1.5 rounded-xl bg-linear-to-br from-tgn01-cta1 to-tgn01-cta2 px-4 text-sm font-bold text-white shadow-[0_8px_20px_-4px_var(--color-tgn01-cta2)] transition-[translate,box-shadow] duration-150 hover:-translate-y-0.5 hover:shadow-[0_12px_26px_-4px_var(--color-tgn01-cta2)] focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-white motion-reduce:transition-none sm:px-5">Start free<span aria-hidden="true" class="transition-transform group-hover:translate-x-0.5">→</span></a>
<button type="button" popovertarget="tgn01-menu" aria-label="Open menu" class="grid size-11 cursor-pointer place-items-center rounded-xl text-tgn01-ink hover:bg-white/55 focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-tgn01-ink md:hidden"><svg class="size-5" viewBox="0 0 20 20" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" aria-hidden="true"><path d="M3 6h14M3 10h14M3 14h14"/></svg></button>
</div>
</header>
<nav id="tgn01-menu" popover aria-label="Mobile primary" class="fixed inset-x-3 top-20 bottom-auto m-0 w-auto rounded-2xl border border-white/70 bg-white/65 p-2 font-tgn01-sans text-tgn01-ink opacity-0 shadow-[0_20px_50px_-12px_oklch(0.25_0.1_285/0.45)] backdrop-blur-xl backdrop-saturate-[1.8] transition-[opacity,translate,overlay,display] transition-discrete duration-200 -translate-y-2 open:translate-y-0 open:opacity-100 starting:open:-translate-y-2 starting:open:opacity-0 motion-reduce:transition-none">
<a href="#" aria-current="page" class="flex h-12 items-center rounded-xl px-4 text-[15px] font-semibold text-tgn01-ink hover:bg-white/60 focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-tgn01-ink">Product</a>
<a href="#" class="flex h-12 items-center rounded-xl px-4 text-[15px] font-semibold text-tgn01-ink hover:bg-white/60 focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-tgn01-ink">Pricing</a>
<a href="#" class="flex h-12 items-center rounded-xl px-4 text-[15px] font-semibold text-tgn01-ink hover:bg-white/60 focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-tgn01-ink">Docs</a>
<a href="#" class="flex h-12 items-center rounded-xl px-4 text-[15px] font-semibold text-tgn01-ink hover:bg-white/60 focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-tgn01-ink">Blog</a>
<a href="#" class="flex h-12 items-center rounded-xl px-4 text-[15px] font-semibold text-tgn01-ink hover:bg-white/60 focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-tgn01-ink mt-1 border-t border-tgn01-ink/10 rounded-t-none">Sign in</a>
</nav>
<div class="max-w-xl px-2 pt-16 pb-6 sm:px-3.5">
<p class="mb-4 inline-flex rounded-full border border-white/40 bg-white/20 px-3 py-1.5 text-xs font-bold tracking-[0.14em] text-white uppercase backdrop-blur-sm">Ship faster</p>
<h2 class="font-tgn01-display text-[clamp(30px,5.4vw,46px)]/[1.04] font-extrabold tracking-[-0.035em] text-balance text-white [text-shadow:0_2px_24px_oklch(0.2_0.1_300/0.3)]">The workspace your whole team ships from.</h2>
</div>
<div class="max-w-2xl px-2 pt-6 pb-20 text-white/95 [text-shadow:0_1px_6px_oklch(0.25_0.1_300/0.35)] sm:px-3.5 [&_p]:mb-3.5 [&_p]:text-[15px]/[1.65] [&_p]:font-medium [&_p]:text-pretty [&_:is(h1,h2,h3)]:text-balance [&_h2]:mt-5 [&_h2]:mb-3.5 [&_h2]:text-[22px]/[1.2] [&_h2]:font-extrabold [&_h2]:tracking-[-0.015em] [&_h3]:mt-8 [&_h3]:mb-3 [&_h3]:text-lg/[1.25] [&_h3]:font-bold [&_h3]:tracking-[-0.01em] [&_:is(h2,h3)]:font-tgn01-display [&_:is(h2,h3)]:text-white [&_code]:rounded-md [&_code]:px-1.5 [&_code]:py-0.5 [&_code]:font-tgn01-mono [&_code]:text-[12.5px] [&_code]:font-medium [&_code]:border [&_code]:border-white/40 [&_code]:bg-white/25 [&_code]:text-white [&_code]:[text-shadow:none]">
<p>The floating glass header stays pinned to the top as you scroll. Translucent white fill + <code>backdrop-filter:blur(16px) saturate(180%)</code> + a 1px hairline — the classic trio.</p>
<p>The <code>saturate(180%)</code> boost is the secret sauce most Tailwind snippets miss. Plain <code>blur()</code> alone looks grey and dead; boosting saturation makes the frosted pane feel like it's actually made of the colours behind it.</p>
<p>Dark link text stays high-contrast even as the gradient shifts underneath, because the fill is white-ish and ≥45% opaque. The blur alone is never enough to guarantee contrast; the fill opacity is the actual floor.</p>
<p>The CTA is a linear-gradient pill with its own coloured shadow so it reads as the single most important control on the page. It lifts on hover with a subtle <code>translateY(-2px)</code>.</p>
<p>For a darker product, flip the fill to <code>rgba(17,17,20,.5)</code> and link colour to near-white — the same structure works as a dark SaaS header without changing a single selector.</p>
<p>Tailwind users: the class equivalent is <code>sticky top-4 backdrop-blur-xl backdrop-saturate-150 bg-white/50 border border-white/60 rounded-2xl shadow-lg</code>. Every declaration maps to a utility class or arbitrary value.</p>
<h3>Why saturate matters more than blur radius</h3>
<p>Increasing the blur radius past 20-24px starts to cost frames on low-end Android hardware. Increasing the saturation stops at zero cost — saturation is a colour matrix operation, not a spatial convolution.</p>
<p>Practical range: <code>blur(12px)</code> at <code>saturate(180%)</code> reads as premium and stays smooth. <code>blur(24px)</code> at <code>saturate(120%)</code> reads as heavy privacy-glass but taxes older devices. Pick the trade-off deliberately.</p>
<p>Test the header over your <em>lightest</em> hero, not your darkest. Dark heroes hide contrast bugs; light heroes reveal them.</p>
<h3>Layout hygiene for sticky glass headers</h3>
<p>The header must have a fixed <code>height</code> declaration (56px in this demo). Sticky elements with intrinsic height can shift as fonts swap in — a real Cumulative Layout Shift hit that Google's Core Web Vitals reports.</p>
<p>Keep the sticky header out of ancestors with <code>overflow:hidden</code> on the block axis. This is the single most common sticky-fails-silently bug — the header renders once at the top and never moves.</p>
<p>Give the containing element a defined block-size (the outer wrapper here is <code>min-height:100vh</code>). Sticky without a resolvable containing block behaves like static.</p>
<p>Above 1200px viewport, consider raising the nav's max-width to keep the CTA anchored to the right edge rather than floating in a wide gap. Below 640px, collapse the primary links into a hamburger and keep the CTA prominent.</p>
<h3>Real SaaS marketing sites shipping this pattern</h3>
<p>Stripe uses a variant with heavier saturation over its animated gradient hero. Linear uses a near-black variant with cyan accent. Vercel uses white glass with brand purple CTA. Superhuman uses navy glass with peach CTA. Framer uses a pill variant of the same recipe (see Demo 04).</p>
<p>Every one of them ships the same three-declaration recipe: translucent fill + <code>backdrop-filter:blur() saturate()</code> + 1px hairline. The palette differs; the structure doesn't.</p>
<p>Keep scrolling — the sticky bar demonstrates its main job by staying pinned as the content flows underneath it.</p>
</div>
</div>
</div>@import "tailwindcss";
@theme {
--color-tgn01-g1: #b981ff;
--color-tgn01-g1: oklch(0.72 0.2 300);
--color-tgn01-g2: #438aff;
--color-tgn01-g2: oklch(0.65 0.19 260);
--color-tgn01-g3: #00bac5;
--color-tgn01-g3: oklch(0.7 0.16 200);
--color-tgn01-ink: #211c48;
--color-tgn01-ink: oklch(0.26 0.08 285);
--color-tgn01-cta1: #e20c35;
--color-tgn01-cta1: oklch(0.58 0.23 22);
--color-tgn01-cta2: #c4008d;
--color-tgn01-cta2: oklch(0.54 0.24 345);
--font-tgn01-display: 'Bricolage Grotesque', system-ui, sans-serif;
--font-tgn01-sans: 'Geist', system-ui, sans-serif;
--font-tgn01-mono: 'Geist Mono', ui-monospace, monospace;
}
/* Root rule: the full-bleed contract, stated in CSS as well as in the markup's utilities, so the
stage is sized before the browser build compiles. */
.tgn-01 {
width: 100%;
min-height: 100svh;
}@import "tailwindcss";
@theme {
--color-tgn01-g1: #b981ff;
--color-tgn01-g1: oklch(0.72 0.2 300);
--color-tgn01-g2: #438aff;
--color-tgn01-g2: oklch(0.65 0.19 260);
--color-tgn01-g3: #00bac5;
--color-tgn01-g3: oklch(0.7 0.16 200);
--color-tgn01-ink: #211c48;
--color-tgn01-ink: oklch(0.26 0.08 285);
--color-tgn01-cta1: #e20c35;
--color-tgn01-cta1: oklch(0.58 0.23 22);
--color-tgn01-cta2: #c4008d;
--color-tgn01-cta2: oklch(0.54 0.24 345);
--font-tgn01-display: 'Bricolage Grotesque', system-ui, sans-serif;
--font-tgn01-sans: 'Geist', system-ui, sans-serif;
--font-tgn01-mono: 'Geist Mono', ui-monospace, monospace;
}
/* Root rule: the full-bleed contract, stated in CSS as well as in the markup's utilities, so the
stage is sized before the browser build compiles. */
.tgn-01 {
width: 100%;
min-height: 100svh;
}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-tgn01-g1: #b981ff;
--color-tgn01-g1: oklch(0.72 0.2 300);
--color-tgn01-g2: #438aff;
--color-tgn01-g2: oklch(0.65 0.19 260);
--color-tgn01-g3: #00bac5;
--color-tgn01-g3: oklch(0.7 0.16 200);
--color-tgn01-ink: #211c48;
--color-tgn01-ink: oklch(0.26 0.08 285);
--color-tgn01-cta1: #e20c35;
--color-tgn01-cta1: oklch(0.58 0.23 22);
--color-tgn01-cta2: #c4008d;
--color-tgn01-cta2: oklch(0.54 0.24 345);
--font-tgn01-display: 'Bricolage Grotesque', system-ui, sans-serif;
--font-tgn01-sans: 'Geist', system-ui, sans-serif;
--font-tgn01-mono: 'Geist Mono', ui-monospace, monospace;
}
/* Root rule: the full-bleed contract, stated in CSS as well as in the markup's utilities, so the
stage is sized before the browser build compiles. */
.tgn-01 {
width: 100%;
min-height: 100svh;
}@import "tailwindcss";
@theme {
--color-tgn01-g1: #b981ff;
--color-tgn01-g1: oklch(0.72 0.2 300);
--color-tgn01-g2: #438aff;
--color-tgn01-g2: oklch(0.65 0.19 260);
--color-tgn01-g3: #00bac5;
--color-tgn01-g3: oklch(0.7 0.16 200);
--color-tgn01-ink: #211c48;
--color-tgn01-ink: oklch(0.26 0.08 285);
--color-tgn01-cta1: #e20c35;
--color-tgn01-cta1: oklch(0.58 0.23 22);
--color-tgn01-cta2: #c4008d;
--color-tgn01-cta2: oklch(0.54 0.24 345);
--font-tgn01-display: 'Bricolage Grotesque', system-ui, sans-serif;
--font-tgn01-sans: 'Geist', system-ui, sans-serif;
--font-tgn01-mono: 'Geist Mono', ui-monospace, monospace;
}
/* Root rule: the full-bleed contract, stated in CSS as well as in the markup's utilities, so the
stage is sized before the browser build compiles. */
.tgn-01 {
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=Bricolage+Grotesque:opsz,wght@12..96,500..800&family=Geist:wght@400..800&family=Geist+Mono:wght@400..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=Bricolage+Grotesque:opsz,wght@12..96,500..800&family=Geist:wght@400..800&family=Geist+Mono:wght@400..600&display=swap">What changed in the port
Which parts became utilities, which stayed CSS, and why.
- Every declaration of
.gn-01-barbecame a utility;-webkit-backdrop-filterdisappeared from the source because Tailwind v4 emits it. :hover,:focus-visibleand the reduced-motion guard moved onto the elements they change ashover:,focus-visible:andmotion-reduce:.- UI upgrade from the CSS original: the primary links were
display:nonebelow 640px; they now open from a 44px menu button in a light-dismissing Popover API glass panel — still zero JS. - UI upgrade: the CTA gradient was darkened (
0.62 → 0.58L) so white label text clears 4.5:1, the active page gets a visiblearia-currentstate, and the headline now scales withclamp()in Bricolage Grotesque.
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 Navbar for SaaS Landing Pages
Source: https://codefronts.com/navigation/tailwind-css-glassmorphic-sticky-navbars/tailwind-glassmorphism-navbar-saas-landing-page/
The query everyone types: a floating frosted-glass SaaS header over a vibrant gradient hero — brand, centred links, ghost sign-in and a gradient CTA. The CSS original's glass trio is now bg-white/50 border-white/60 backdrop-blur-lg backdrop-saturate-[1.8], and the links it simply hid on phones now live in a zero-JS Popover API glass menu.
## HTML
```html
<div class="tgn-01 w-full min-h-svh bg-tgn01-g2 bg-[radial-gradient(120%_120%_at_12%_0%,var(--color-tgn01-g1)_0%,var(--color-tgn01-g2)_40%,var(--color-tgn01-g3)_100%)] font-tgn01-sans">
<div class="relative h-svh overflow-y-auto scroll-smooth p-3 sm:p-5">
<header class="sticky top-3 z-10 flex h-16 items-center gap-4 rounded-2xl border border-white/60 bg-white/50 py-2.5 pr-2.5 pl-4 shadow-[0_8px_30px_-6px_oklch(0.25_0.1_285/0.35)] backdrop-blur-lg backdrop-saturate-[1.8] not-supports-[backdrop-filter:blur(1px)]:bg-white/90 sm:pl-5">
<a class="flex items-center gap-2.5 rounded-lg font-tgn01-display text-lg font-extrabold tracking-[-0.03em] text-tgn01-ink focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-tgn01-ink" href="#"><span aria-hidden="true" class="grid size-8 place-items-center rounded-[10px] bg-linear-to-br from-tgn01-cta1 to-tgn01-cta2 text-xs text-white shadow-[0_4px_12px_-2px_var(--color-tgn01-cta2)]">◆</span>Nimbus</a>
<nav class="mx-auto max-md:hidden" aria-label="Primary">
<ul class="flex gap-1">
<li><a href="#" aria-current="page" class="flex h-11 items-center rounded-xl px-3.5 text-sm font-semibold text-tgn01-ink/80 transition-colors hover:bg-white/55 hover:text-tgn01-ink aria-[current=page]:bg-white/70 aria-[current=page]:text-tgn01-ink focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-tgn01-ink">Product</a></li>
<li><a href="#" class="flex h-11 items-center rounded-xl px-3.5 text-sm font-semibold text-tgn01-ink/80 transition-colors hover:bg-white/55 hover:text-tgn01-ink aria-[current=page]:bg-white/70 aria-[current=page]:text-tgn01-ink focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-tgn01-ink">Pricing</a></li>
<li><a href="#" class="flex h-11 items-center rounded-xl px-3.5 text-sm font-semibold text-tgn01-ink/80 transition-colors hover:bg-white/55 hover:text-tgn01-ink aria-[current=page]:bg-white/70 aria-[current=page]:text-tgn01-ink focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-tgn01-ink">Docs</a></li>
<li><a href="#" class="flex h-11 items-center rounded-xl px-3.5 text-sm font-semibold text-tgn01-ink/80 transition-colors hover:bg-white/55 hover:text-tgn01-ink aria-[current=page]:bg-white/70 aria-[current=page]:text-tgn01-ink focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-tgn01-ink">Blog</a></li>
</ul>
</nav>
<div class="flex items-center gap-1.5 max-md:ml-auto">
<a href="#" class="flex h-11 items-center rounded-xl px-3.5 text-sm font-semibold text-tgn01-ink/80 transition-colors hover:bg-white/55 hover:text-tgn01-ink aria-[current=page]:bg-white/70 aria-[current=page]:text-tgn01-ink focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-tgn01-ink max-sm:hidden">Sign in</a>
<a href="#" class="group flex h-11 items-center gap-1.5 rounded-xl bg-linear-to-br from-tgn01-cta1 to-tgn01-cta2 px-4 text-sm font-bold text-white shadow-[0_8px_20px_-4px_var(--color-tgn01-cta2)] transition-[translate,box-shadow] duration-150 hover:-translate-y-0.5 hover:shadow-[0_12px_26px_-4px_var(--color-tgn01-cta2)] focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-white motion-reduce:transition-none sm:px-5">Start free<span aria-hidden="true" class="transition-transform group-hover:translate-x-0.5">→</span></a>
<button type="button" popovertarget="tgn01-menu" aria-label="Open menu" class="grid size-11 cursor-pointer place-items-center rounded-xl text-tgn01-ink hover:bg-white/55 focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-tgn01-ink md:hidden"><svg class="size-5" viewBox="0 0 20 20" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" aria-hidden="true"><path d="M3 6h14M3 10h14M3 14h14"/></svg></button>
</div>
</header>
<nav id="tgn01-menu" popover aria-label="Mobile primary" class="fixed inset-x-3 top-20 bottom-auto m-0 w-auto rounded-2xl border border-white/70 bg-white/65 p-2 font-tgn01-sans text-tgn01-ink opacity-0 shadow-[0_20px_50px_-12px_oklch(0.25_0.1_285/0.45)] backdrop-blur-xl backdrop-saturate-[1.8] transition-[opacity,translate,overlay,display] transition-discrete duration-200 -translate-y-2 open:translate-y-0 open:opacity-100 starting:open:-translate-y-2 starting:open:opacity-0 motion-reduce:transition-none">
<a href="#" aria-current="page" class="flex h-12 items-center rounded-xl px-4 text-[15px] font-semibold text-tgn01-ink hover:bg-white/60 focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-tgn01-ink">Product</a>
<a href="#" class="flex h-12 items-center rounded-xl px-4 text-[15px] font-semibold text-tgn01-ink hover:bg-white/60 focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-tgn01-ink">Pricing</a>
<a href="#" class="flex h-12 items-center rounded-xl px-4 text-[15px] font-semibold text-tgn01-ink hover:bg-white/60 focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-tgn01-ink">Docs</a>
<a href="#" class="flex h-12 items-center rounded-xl px-4 text-[15px] font-semibold text-tgn01-ink hover:bg-white/60 focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-tgn01-ink">Blog</a>
<a href="#" class="flex h-12 items-center rounded-xl px-4 text-[15px] font-semibold text-tgn01-ink hover:bg-white/60 focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-tgn01-ink mt-1 border-t border-tgn01-ink/10 rounded-t-none">Sign in</a>
</nav>
<div class="max-w-xl px-2 pt-16 pb-6 sm:px-3.5">
<p class="mb-4 inline-flex rounded-full border border-white/40 bg-white/20 px-3 py-1.5 text-xs font-bold tracking-[0.14em] text-white uppercase backdrop-blur-sm">Ship faster</p>
<h2 class="font-tgn01-display text-[clamp(30px,5.4vw,46px)]/[1.04] font-extrabold tracking-[-0.035em] text-balance text-white [text-shadow:0_2px_24px_oklch(0.2_0.1_300/0.3)]">The workspace your whole team ships from.</h2>
</div>
<div class="max-w-2xl px-2 pt-6 pb-20 text-white/95 [text-shadow:0_1px_6px_oklch(0.25_0.1_300/0.35)] sm:px-3.5 [&_p]:mb-3.5 [&_p]:text-[15px]/[1.65] [&_p]:font-medium [&_p]:text-pretty [&_:is(h1,h2,h3)]:text-balance [&_h2]:mt-5 [&_h2]:mb-3.5 [&_h2]:text-[22px]/[1.2] [&_h2]:font-extrabold [&_h2]:tracking-[-0.015em] [&_h3]:mt-8 [&_h3]:mb-3 [&_h3]:text-lg/[1.25] [&_h3]:font-bold [&_h3]:tracking-[-0.01em] [&_:is(h2,h3)]:font-tgn01-display [&_:is(h2,h3)]:text-white [&_code]:rounded-md [&_code]:px-1.5 [&_code]:py-0.5 [&_code]:font-tgn01-mono [&_code]:text-[12.5px] [&_code]:font-medium [&_code]:border [&_code]:border-white/40 [&_code]:bg-white/25 [&_code]:text-white [&_code]:[text-shadow:none]">
<p>The floating glass header stays pinned to the top as you scroll. Translucent white fill + <code>backdrop-filter:blur(16px) saturate(180%)</code> + a 1px hairline — the classic trio.</p>
<p>The <code>saturate(180%)</code> boost is the secret sauce most Tailwind snippets miss. Plain <code>blur()</code> alone looks grey and dead; boosting saturation makes the frosted pane feel like it's actually made of the colours behind it.</p>
<p>Dark link text stays high-contrast even as the gradient shifts underneath, because the fill is white-ish and ≥45% opaque. The blur alone is never enough to guarantee contrast; the fill opacity is the actual floor.</p>
<p>The CTA is a linear-gradient pill with its own coloured shadow so it reads as the single most important control on the page. It lifts on hover with a subtle <code>translateY(-2px)</code>.</p>
<p>For a darker product, flip the fill to <code>rgba(17,17,20,.5)</code> and link colour to near-white — the same structure works as a dark SaaS header without changing a single selector.</p>
<p>Tailwind users: the class equivalent is <code>sticky top-4 backdrop-blur-xl backdrop-saturate-150 bg-white/50 border border-white/60 rounded-2xl shadow-lg</code>. Every declaration maps to a utility class or arbitrary value.</p>
<h3>Why saturate matters more than blur radius</h3>
<p>Increasing the blur radius past 20-24px starts to cost frames on low-end Android hardware. Increasing the saturation stops at zero cost — saturation is a colour matrix operation, not a spatial convolution.</p>
<p>Practical range: <code>blur(12px)</code> at <code>saturate(180%)</code> reads as premium and stays smooth. <code>blur(24px)</code> at <code>saturate(120%)</code> reads as heavy privacy-glass but taxes older devices. Pick the trade-off deliberately.</p>
<p>Test the header over your <em>lightest</em> hero, not your darkest. Dark heroes hide contrast bugs; light heroes reveal them.</p>
<h3>Layout hygiene for sticky glass headers</h3>
<p>The header must have a fixed <code>height</code> declaration (56px in this demo). Sticky elements with intrinsic height can shift as fonts swap in — a real Cumulative Layout Shift hit that Google's Core Web Vitals reports.</p>
<p>Keep the sticky header out of ancestors with <code>overflow:hidden</code> on the block axis. This is the single most common sticky-fails-silently bug — the header renders once at the top and never moves.</p>
<p>Give the containing element a defined block-size (the outer wrapper here is <code>min-height:100vh</code>). Sticky without a resolvable containing block behaves like static.</p>
<p>Above 1200px viewport, consider raising the nav's max-width to keep the CTA anchored to the right edge rather than floating in a wide gap. Below 640px, collapse the primary links into a hamburger and keep the CTA prominent.</p>
<h3>Real SaaS marketing sites shipping this pattern</h3>
<p>Stripe uses a variant with heavier saturation over its animated gradient hero. Linear uses a near-black variant with cyan accent. Vercel uses white glass with brand purple CTA. Superhuman uses navy glass with peach CTA. Framer uses a pill variant of the same recipe (see Demo 04).</p>
<p>Every one of them ships the same three-declaration recipe: translucent fill + <code>backdrop-filter:blur() saturate()</code> + 1px hairline. The palette differs; the structure doesn't.</p>
<p>Keep scrolling — the sticky bar demonstrates its main job by staying pinned as the content flows underneath it.</p>
</div>
</div>
</div>
```
## CSS
```css
@import "tailwindcss";
@theme {
--color-tgn01-g1: #b981ff;
--color-tgn01-g1: oklch(0.72 0.2 300);
--color-tgn01-g2: #438aff;
--color-tgn01-g2: oklch(0.65 0.19 260);
--color-tgn01-g3: #00bac5;
--color-tgn01-g3: oklch(0.7 0.16 200);
--color-tgn01-ink: #211c48;
--color-tgn01-ink: oklch(0.26 0.08 285);
--color-tgn01-cta1: #e20c35;
--color-tgn01-cta1: oklch(0.58 0.23 22);
--color-tgn01-cta2: #c4008d;
--color-tgn01-cta2: oklch(0.54 0.24 345);
--font-tgn01-display: 'Bricolage Grotesque', system-ui, sans-serif;
--font-tgn01-sans: 'Geist', system-ui, sans-serif;
--font-tgn01-mono: 'Geist Mono', ui-monospace, monospace;
}
/* Root rule: the full-bleed contract, stated in CSS as well as in the markup's utilities, so the
stage is sized before the browser build compiles. */
.tgn-01 {
width: 100%;
min-height: 100svh;
}
```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 Navbar for SaaS Landing Pages
Source: https://codefronts.com/navigation/tailwind-css-glassmorphic-sticky-navbars/tailwind-glassmorphism-navbar-saas-landing-page/
The query everyone types: a floating frosted-glass SaaS header over a vibrant gradient hero — brand, centred links, ghost sign-in and a gradient CTA. The CSS original's glass trio is now bg-white/50 border-white/60 backdrop-blur-lg backdrop-saturate-[1.8], and the links it simply hid on phones now live in a zero-JS Popover API glass menu.
## HTML
```html
<div class="tgn-01 w-full min-h-svh bg-tgn01-g2 bg-[radial-gradient(120%_120%_at_12%_0%,var(--color-tgn01-g1)_0%,var(--color-tgn01-g2)_40%,var(--color-tgn01-g3)_100%)] font-tgn01-sans">
<div class="relative h-svh overflow-y-auto scroll-smooth p-3 sm:p-5">
<header class="sticky top-3 z-10 flex h-16 items-center gap-4 rounded-2xl border border-white/60 bg-white/50 py-2.5 pr-2.5 pl-4 shadow-[0_8px_30px_-6px_oklch(0.25_0.1_285/0.35)] backdrop-blur-lg backdrop-saturate-[1.8] not-supports-[backdrop-filter:blur(1px)]:bg-white/90 sm:pl-5">
<a class="flex items-center gap-2.5 rounded-lg font-tgn01-display text-lg font-extrabold tracking-[-0.03em] text-tgn01-ink focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-tgn01-ink" href="#"><span aria-hidden="true" class="grid size-8 place-items-center rounded-[10px] bg-linear-to-br from-tgn01-cta1 to-tgn01-cta2 text-xs text-white shadow-[0_4px_12px_-2px_var(--color-tgn01-cta2)]">◆</span>Nimbus</a>
<nav class="mx-auto max-md:hidden" aria-label="Primary">
<ul class="flex gap-1">
<li><a href="#" aria-current="page" class="flex h-11 items-center rounded-xl px-3.5 text-sm font-semibold text-tgn01-ink/80 transition-colors hover:bg-white/55 hover:text-tgn01-ink aria-[current=page]:bg-white/70 aria-[current=page]:text-tgn01-ink focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-tgn01-ink">Product</a></li>
<li><a href="#" class="flex h-11 items-center rounded-xl px-3.5 text-sm font-semibold text-tgn01-ink/80 transition-colors hover:bg-white/55 hover:text-tgn01-ink aria-[current=page]:bg-white/70 aria-[current=page]:text-tgn01-ink focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-tgn01-ink">Pricing</a></li>
<li><a href="#" class="flex h-11 items-center rounded-xl px-3.5 text-sm font-semibold text-tgn01-ink/80 transition-colors hover:bg-white/55 hover:text-tgn01-ink aria-[current=page]:bg-white/70 aria-[current=page]:text-tgn01-ink focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-tgn01-ink">Docs</a></li>
<li><a href="#" class="flex h-11 items-center rounded-xl px-3.5 text-sm font-semibold text-tgn01-ink/80 transition-colors hover:bg-white/55 hover:text-tgn01-ink aria-[current=page]:bg-white/70 aria-[current=page]:text-tgn01-ink focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-tgn01-ink">Blog</a></li>
</ul>
</nav>
<div class="flex items-center gap-1.5 max-md:ml-auto">
<a href="#" class="flex h-11 items-center rounded-xl px-3.5 text-sm font-semibold text-tgn01-ink/80 transition-colors hover:bg-white/55 hover:text-tgn01-ink aria-[current=page]:bg-white/70 aria-[current=page]:text-tgn01-ink focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-tgn01-ink max-sm:hidden">Sign in</a>
<a href="#" class="group flex h-11 items-center gap-1.5 rounded-xl bg-linear-to-br from-tgn01-cta1 to-tgn01-cta2 px-4 text-sm font-bold text-white shadow-[0_8px_20px_-4px_var(--color-tgn01-cta2)] transition-[translate,box-shadow] duration-150 hover:-translate-y-0.5 hover:shadow-[0_12px_26px_-4px_var(--color-tgn01-cta2)] focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-white motion-reduce:transition-none sm:px-5">Start free<span aria-hidden="true" class="transition-transform group-hover:translate-x-0.5">→</span></a>
<button type="button" popovertarget="tgn01-menu" aria-label="Open menu" class="grid size-11 cursor-pointer place-items-center rounded-xl text-tgn01-ink hover:bg-white/55 focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-tgn01-ink md:hidden"><svg class="size-5" viewBox="0 0 20 20" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" aria-hidden="true"><path d="M3 6h14M3 10h14M3 14h14"/></svg></button>
</div>
</header>
<nav id="tgn01-menu" popover aria-label="Mobile primary" class="fixed inset-x-3 top-20 bottom-auto m-0 w-auto rounded-2xl border border-white/70 bg-white/65 p-2 font-tgn01-sans text-tgn01-ink opacity-0 shadow-[0_20px_50px_-12px_oklch(0.25_0.1_285/0.45)] backdrop-blur-xl backdrop-saturate-[1.8] transition-[opacity,translate,overlay,display] transition-discrete duration-200 -translate-y-2 open:translate-y-0 open:opacity-100 starting:open:-translate-y-2 starting:open:opacity-0 motion-reduce:transition-none">
<a href="#" aria-current="page" class="flex h-12 items-center rounded-xl px-4 text-[15px] font-semibold text-tgn01-ink hover:bg-white/60 focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-tgn01-ink">Product</a>
<a href="#" class="flex h-12 items-center rounded-xl px-4 text-[15px] font-semibold text-tgn01-ink hover:bg-white/60 focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-tgn01-ink">Pricing</a>
<a href="#" class="flex h-12 items-center rounded-xl px-4 text-[15px] font-semibold text-tgn01-ink hover:bg-white/60 focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-tgn01-ink">Docs</a>
<a href="#" class="flex h-12 items-center rounded-xl px-4 text-[15px] font-semibold text-tgn01-ink hover:bg-white/60 focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-tgn01-ink">Blog</a>
<a href="#" class="flex h-12 items-center rounded-xl px-4 text-[15px] font-semibold text-tgn01-ink hover:bg-white/60 focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-tgn01-ink mt-1 border-t border-tgn01-ink/10 rounded-t-none">Sign in</a>
</nav>
<div class="max-w-xl px-2 pt-16 pb-6 sm:px-3.5">
<p class="mb-4 inline-flex rounded-full border border-white/40 bg-white/20 px-3 py-1.5 text-xs font-bold tracking-[0.14em] text-white uppercase backdrop-blur-sm">Ship faster</p>
<h2 class="font-tgn01-display text-[clamp(30px,5.4vw,46px)]/[1.04] font-extrabold tracking-[-0.035em] text-balance text-white [text-shadow:0_2px_24px_oklch(0.2_0.1_300/0.3)]">The workspace your whole team ships from.</h2>
</div>
<div class="max-w-2xl px-2 pt-6 pb-20 text-white/95 [text-shadow:0_1px_6px_oklch(0.25_0.1_300/0.35)] sm:px-3.5 [&_p]:mb-3.5 [&_p]:text-[15px]/[1.65] [&_p]:font-medium [&_p]:text-pretty [&_:is(h1,h2,h3)]:text-balance [&_h2]:mt-5 [&_h2]:mb-3.5 [&_h2]:text-[22px]/[1.2] [&_h2]:font-extrabold [&_h2]:tracking-[-0.015em] [&_h3]:mt-8 [&_h3]:mb-3 [&_h3]:text-lg/[1.25] [&_h3]:font-bold [&_h3]:tracking-[-0.01em] [&_:is(h2,h3)]:font-tgn01-display [&_:is(h2,h3)]:text-white [&_code]:rounded-md [&_code]:px-1.5 [&_code]:py-0.5 [&_code]:font-tgn01-mono [&_code]:text-[12.5px] [&_code]:font-medium [&_code]:border [&_code]:border-white/40 [&_code]:bg-white/25 [&_code]:text-white [&_code]:[text-shadow:none]">
<p>The floating glass header stays pinned to the top as you scroll. Translucent white fill + <code>backdrop-filter:blur(16px) saturate(180%)</code> + a 1px hairline — the classic trio.</p>
<p>The <code>saturate(180%)</code> boost is the secret sauce most Tailwind snippets miss. Plain <code>blur()</code> alone looks grey and dead; boosting saturation makes the frosted pane feel like it's actually made of the colours behind it.</p>
<p>Dark link text stays high-contrast even as the gradient shifts underneath, because the fill is white-ish and ≥45% opaque. The blur alone is never enough to guarantee contrast; the fill opacity is the actual floor.</p>
<p>The CTA is a linear-gradient pill with its own coloured shadow so it reads as the single most important control on the page. It lifts on hover with a subtle <code>translateY(-2px)</code>.</p>
<p>For a darker product, flip the fill to <code>rgba(17,17,20,.5)</code> and link colour to near-white — the same structure works as a dark SaaS header without changing a single selector.</p>
<p>Tailwind users: the class equivalent is <code>sticky top-4 backdrop-blur-xl backdrop-saturate-150 bg-white/50 border border-white/60 rounded-2xl shadow-lg</code>. Every declaration maps to a utility class or arbitrary value.</p>
<h3>Why saturate matters more than blur radius</h3>
<p>Increasing the blur radius past 20-24px starts to cost frames on low-end Android hardware. Increasing the saturation stops at zero cost — saturation is a colour matrix operation, not a spatial convolution.</p>
<p>Practical range: <code>blur(12px)</code> at <code>saturate(180%)</code> reads as premium and stays smooth. <code>blur(24px)</code> at <code>saturate(120%)</code> reads as heavy privacy-glass but taxes older devices. Pick the trade-off deliberately.</p>
<p>Test the header over your <em>lightest</em> hero, not your darkest. Dark heroes hide contrast bugs; light heroes reveal them.</p>
<h3>Layout hygiene for sticky glass headers</h3>
<p>The header must have a fixed <code>height</code> declaration (56px in this demo). Sticky elements with intrinsic height can shift as fonts swap in — a real Cumulative Layout Shift hit that Google's Core Web Vitals reports.</p>
<p>Keep the sticky header out of ancestors with <code>overflow:hidden</code> on the block axis. This is the single most common sticky-fails-silently bug — the header renders once at the top and never moves.</p>
<p>Give the containing element a defined block-size (the outer wrapper here is <code>min-height:100vh</code>). Sticky without a resolvable containing block behaves like static.</p>
<p>Above 1200px viewport, consider raising the nav's max-width to keep the CTA anchored to the right edge rather than floating in a wide gap. Below 640px, collapse the primary links into a hamburger and keep the CTA prominent.</p>
<h3>Real SaaS marketing sites shipping this pattern</h3>
<p>Stripe uses a variant with heavier saturation over its animated gradient hero. Linear uses a near-black variant with cyan accent. Vercel uses white glass with brand purple CTA. Superhuman uses navy glass with peach CTA. Framer uses a pill variant of the same recipe (see Demo 04).</p>
<p>Every one of them ships the same three-declaration recipe: translucent fill + <code>backdrop-filter:blur() saturate()</code> + 1px hairline. The palette differs; the structure doesn't.</p>
<p>Keep scrolling — the sticky bar demonstrates its main job by staying pinned as the content flows underneath it.</p>
</div>
</div>
</div>
```
## CSS
```css
@import "tailwindcss";
@theme {
--color-tgn01-g1: #b981ff;
--color-tgn01-g1: oklch(0.72 0.2 300);
--color-tgn01-g2: #438aff;
--color-tgn01-g2: oklch(0.65 0.19 260);
--color-tgn01-g3: #00bac5;
--color-tgn01-g3: oklch(0.7 0.16 200);
--color-tgn01-ink: #211c48;
--color-tgn01-ink: oklch(0.26 0.08 285);
--color-tgn01-cta1: #e20c35;
--color-tgn01-cta1: oklch(0.58 0.23 22);
--color-tgn01-cta2: #c4008d;
--color-tgn01-cta2: oklch(0.54 0.24 345);
--font-tgn01-display: 'Bricolage Grotesque', system-ui, sans-serif;
--font-tgn01-sans: 'Geist', system-ui, sans-serif;
--font-tgn01-mono: 'Geist Mono', ui-monospace, monospace;
}
/* Root rule: the full-bleed contract, stated in CSS as well as in the markup's utilities, so the
stage is sized before the browser build compiles. */
.tgn-01 {
width: 100%;
min-height: 100svh;
}
```How this works
The glass trio, as utilities. Fill, filter and hairline sit on the header itself:
<header class="sticky top-3 rounded-2xl border border-white/60 bg-white/50
backdrop-blur-lg backdrop-saturate-[1.8] shadow-[0_8px_30px_-6px_…]">Saturate is the secret. Blur alone samples the hero into grey; backdrop-saturate-[1.8] pushes the sampled colour back up so the pane looks made of the gradient behind it.
The mobile menu is a popover. <button popovertarget="tgn01-menu"> toggles a top-layer panel; open:opacity-100 and starting:open:opacity-0 fade it in, and transition-discrete lets it fade out before display:none lands. Esc and click-outside close it for free.
Make it yours
- Brand hues: edit
--color-tgn01-cta1/cta2in@theme— the CTA gradient, its glow and the logo tile all follow. - Heavier frost: swap
backdrop-blur-lg(16px) forbackdrop-blur-xl(24px) over busy photography. - Dark SaaS:
bg-zinc-950/50 border-white/10and fliptext-tgn01-inktotext-white. - Full-width bar: drop
rounded-2xland the stage padding, and changetop-3totop-0.
Gotchas — read before shipping
- A
filter,opacitybelow 1 orbackdrop-filteron an ancestor makes it a backdrop root — the header then blurs only that ancestor, not the page. - The popover renders in the top layer, so it ignores the header's
z-index; position it withinset-x-3 top-20, not relative to the button. - Test contrast over the lightest part of your hero; the fill opacity, not the blur, is the WCAG floor.
Browser support
| Chrome | Safari | Firefox | Edge |
|---|---|---|---|
| 114+ | 17+ | 128+ | 114+ |
Popover API is Baseline 2024; starting: entry is progressive (without it the menu appears instantly). The floor is Tailwind v4's own sheet.