18 / 22
All 22 in 22 Tailwind Dropdown Menus
- 01Tailwind Slide-Down Fade Dropdown Menu
- 02Tailwind Clip-Path Curtain Reveal Dropdown
- 03Tailwind 3D Perspective Flip Dropdown
- 04Tailwind Elastic Bounce Dropdown Menu
- 05Tailwind Glassmorphism Float Panel Dropdown
- 06Tailwind Stagger Children Reveal Dropdown
- 07Tailwind Mega Menu Grid Dropdown
- 08Tailwind Underline Nav Fade Panel Dropdown
- 09Tailwind Details Summary Native Dropdown
- 10Tailwind Checkbox Hack Mobile Nav Dropdown
- 11Tailwind Nested Multi-Level Dropdown
- 12Tailwind Icon Sidebar Flyout Dropdown
- 13Tailwind Split-Screen Mega Menu Dropdown
- 14Tailwind Segmented Pill Nav Dropdown
- 15Tailwind Color Swatch Picker Dropdown
- 16Tailwind Right-Click Context Menu Dropdown
- 17Tailwind Keyboard Accessible ARIA Dropdown
- 18Tailwind Stagger Blur Entrance Dropdown
- 19Tailwind Command Palette Search Dropdown
- 20Tailwind Autocomplete Suggestion Dropdown
- 21Tailwind Tab Panel Dropdown
- 22Tailwind Custom Animated Select Dropdown
Tailwind Stagger Blur Entrance Dropdown
Items that crystallise out of a frosted blur, one after another. The CSS version computes the stagger in JavaScript and writes inline transitionDelay on every item; here the delays are declarative — style="--i:3" plus one utility — and the script shrinks to a single attribute toggle.
Untitled UI Pro: 5,000+ React + Tailwind CSS v4 components · from $349 one-time
Untitled UI React · Affiliate link
The code
<section class="tdd-18 w-full min-h-svh grid justify-center content-start bg-linear-[135deg,var(--color-tdd18-bg1),var(--color-tdd18-bg2)] font-tdd18-sans text-tdd18-ink px-5 py-9" aria-label="Stagger blur entrance dropdown demo">
<nav class="flex w-[min(480px,100%)] items-center justify-between rounded-2xl border border-tdd18-edge bg-white px-4 py-3 shadow-[0_4px_20px_oklch(0.54_0.24_295/0.1)]" aria-label="Primary">
<span class="text-lg font-bold tracking-[-0.5px] text-tdd18-acc">Specter</span>
<div class="group relative">
<button type="button" id="tdd18-btn" aria-expanded="false" aria-controls="tdd18-panel" class="flex min-h-11 cursor-pointer items-center gap-2 rounded-[10px] border-0 bg-tdd18-acc px-4.5 py-2 font-tdd18-sans text-sm font-semibold text-white transition-opacity duration-150 hover:opacity-90 focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-tdd18-acc aria-expanded:opacity-85">
Menu
<span class="size-2 rounded-full bg-tdd18-dot transition-[scale,background] duration-300 ease-tdd18 group-data-open:scale-150 group-data-open:bg-tdd18-dot2 motion-reduce:transition-none" aria-hidden="true"></span>
</button>
<div id="tdd18-panel" class="pointer-events-none invisible absolute top-[calc(100%+10px)] right-0 flex min-w-50 flex-col gap-0.5 rounded-2xl border border-tdd18-edge bg-white p-2 opacity-0 shadow-[0_12px_40px_oklch(0.54_0.24_295/0.18)] transition-[opacity,visibility] duration-200 group-data-open:pointer-events-auto group-data-open:visible group-data-open:opacity-100">
<a href="#launch" style="--i:0" class="flex items-center gap-2.5 rounded-[10px] px-3.5 py-2.5 text-[13.5px] font-medium text-tdd18-ink no-underline opacity-0 translate-y-1.5 blur-[6px] transition-[opacity,translate,filter,background] duration-300 hover:bg-tdd18-tint focus-visible:bg-tdd18-tint focus-visible:outline-none group-data-open:translate-y-0 group-data-open:opacity-100 group-data-open:blur-none group-data-open:[transition-delay:calc(var(--i)*55ms)] motion-reduce:blur-none motion-reduce:[transition-delay:0ms]">🚀 Launch</a>
<a href="#discover" style="--i:1" class="flex items-center gap-2.5 rounded-[10px] px-3.5 py-2.5 text-[13.5px] font-medium text-tdd18-ink no-underline opacity-0 translate-y-1.5 blur-[6px] transition-[opacity,translate,filter,background] duration-300 hover:bg-tdd18-tint focus-visible:bg-tdd18-tint focus-visible:outline-none group-data-open:translate-y-0 group-data-open:opacity-100 group-data-open:blur-none group-data-open:[transition-delay:calc(var(--i)*55ms)] motion-reduce:blur-none motion-reduce:[transition-delay:0ms]">🌟 Discover</a>
<a href="#metrics" style="--i:2" class="flex items-center gap-2.5 rounded-[10px] px-3.5 py-2.5 text-[13.5px] font-medium text-tdd18-ink no-underline opacity-0 translate-y-1.5 blur-[6px] transition-[opacity,translate,filter,background] duration-300 hover:bg-tdd18-tint focus-visible:bg-tdd18-tint focus-visible:outline-none group-data-open:translate-y-0 group-data-open:opacity-100 group-data-open:blur-none group-data-open:[transition-delay:calc(var(--i)*55ms)] motion-reduce:blur-none motion-reduce:[transition-delay:0ms]">📊 Metrics</a>
<a href="#community" style="--i:3" class="flex items-center gap-2.5 rounded-[10px] px-3.5 py-2.5 text-[13.5px] font-medium text-tdd18-ink no-underline opacity-0 translate-y-1.5 blur-[6px] transition-[opacity,translate,filter,background] duration-300 hover:bg-tdd18-tint focus-visible:bg-tdd18-tint focus-visible:outline-none group-data-open:translate-y-0 group-data-open:opacity-100 group-data-open:blur-none group-data-open:[transition-delay:calc(var(--i)*55ms)] motion-reduce:blur-none motion-reduce:[transition-delay:0ms]">💬 Community</a>
<a href="#security" style="--i:4" class="flex items-center gap-2.5 rounded-[10px] px-3.5 py-2.5 text-[13.5px] font-medium text-tdd18-ink no-underline opacity-0 translate-y-1.5 blur-[6px] transition-[opacity,translate,filter,background] duration-300 hover:bg-tdd18-tint focus-visible:bg-tdd18-tint focus-visible:outline-none group-data-open:translate-y-0 group-data-open:opacity-100 group-data-open:blur-none group-data-open:[transition-delay:calc(var(--i)*55ms)] motion-reduce:blur-none motion-reduce:[transition-delay:0ms]">🔒 Security</a>
<div class="my-1 h-px bg-tdd18-edge" aria-hidden="true"></div>
<a href="#upgrade" style="--i:5" class="flex items-center gap-2.5 rounded-[10px] px-3.5 py-2.5 text-[13.5px] font-bold text-tdd18-acc no-underline opacity-0 translate-y-1.5 blur-[6px] transition-[opacity,translate,filter,background] duration-300 hover:bg-tdd18-tint focus-visible:bg-tdd18-tint focus-visible:outline-none group-data-open:translate-y-0 group-data-open:opacity-100 group-data-open:blur-none group-data-open:[transition-delay:calc(var(--i)*55ms)] motion-reduce:blur-none motion-reduce:[transition-delay:0ms]">⚡ Upgrade</a>
</div>
</div>
</nav>
</section><section class="tdd-18 w-full min-h-svh grid justify-center content-start bg-linear-[135deg,var(--color-tdd18-bg1),var(--color-tdd18-bg2)] font-tdd18-sans text-tdd18-ink px-5 py-9" aria-label="Stagger blur entrance dropdown demo">
<nav class="flex w-[min(480px,100%)] items-center justify-between rounded-2xl border border-tdd18-edge bg-white px-4 py-3 shadow-[0_4px_20px_oklch(0.54_0.24_295/0.1)]" aria-label="Primary">
<span class="text-lg font-bold tracking-[-0.5px] text-tdd18-acc">Specter</span>
<div class="group relative">
<button type="button" id="tdd18-btn" aria-expanded="false" aria-controls="tdd18-panel" class="flex min-h-11 cursor-pointer items-center gap-2 rounded-[10px] border-0 bg-tdd18-acc px-4.5 py-2 font-tdd18-sans text-sm font-semibold text-white transition-opacity duration-150 hover:opacity-90 focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-tdd18-acc aria-expanded:opacity-85">
Menu
<span class="size-2 rounded-full bg-tdd18-dot transition-[scale,background] duration-300 ease-tdd18 group-data-open:scale-150 group-data-open:bg-tdd18-dot2 motion-reduce:transition-none" aria-hidden="true"></span>
</button>
<div id="tdd18-panel" class="pointer-events-none invisible absolute top-[calc(100%+10px)] right-0 flex min-w-50 flex-col gap-0.5 rounded-2xl border border-tdd18-edge bg-white p-2 opacity-0 shadow-[0_12px_40px_oklch(0.54_0.24_295/0.18)] transition-[opacity,visibility] duration-200 group-data-open:pointer-events-auto group-data-open:visible group-data-open:opacity-100">
<a href="#launch" style="--i:0" class="flex items-center gap-2.5 rounded-[10px] px-3.5 py-2.5 text-[13.5px] font-medium text-tdd18-ink no-underline opacity-0 translate-y-1.5 blur-[6px] transition-[opacity,translate,filter,background] duration-300 hover:bg-tdd18-tint focus-visible:bg-tdd18-tint focus-visible:outline-none group-data-open:translate-y-0 group-data-open:opacity-100 group-data-open:blur-none group-data-open:[transition-delay:calc(var(--i)*55ms)] motion-reduce:blur-none motion-reduce:[transition-delay:0ms]">🚀 Launch</a>
<a href="#discover" style="--i:1" class="flex items-center gap-2.5 rounded-[10px] px-3.5 py-2.5 text-[13.5px] font-medium text-tdd18-ink no-underline opacity-0 translate-y-1.5 blur-[6px] transition-[opacity,translate,filter,background] duration-300 hover:bg-tdd18-tint focus-visible:bg-tdd18-tint focus-visible:outline-none group-data-open:translate-y-0 group-data-open:opacity-100 group-data-open:blur-none group-data-open:[transition-delay:calc(var(--i)*55ms)] motion-reduce:blur-none motion-reduce:[transition-delay:0ms]">🌟 Discover</a>
<a href="#metrics" style="--i:2" class="flex items-center gap-2.5 rounded-[10px] px-3.5 py-2.5 text-[13.5px] font-medium text-tdd18-ink no-underline opacity-0 translate-y-1.5 blur-[6px] transition-[opacity,translate,filter,background] duration-300 hover:bg-tdd18-tint focus-visible:bg-tdd18-tint focus-visible:outline-none group-data-open:translate-y-0 group-data-open:opacity-100 group-data-open:blur-none group-data-open:[transition-delay:calc(var(--i)*55ms)] motion-reduce:blur-none motion-reduce:[transition-delay:0ms]">📊 Metrics</a>
<a href="#community" style="--i:3" class="flex items-center gap-2.5 rounded-[10px] px-3.5 py-2.5 text-[13.5px] font-medium text-tdd18-ink no-underline opacity-0 translate-y-1.5 blur-[6px] transition-[opacity,translate,filter,background] duration-300 hover:bg-tdd18-tint focus-visible:bg-tdd18-tint focus-visible:outline-none group-data-open:translate-y-0 group-data-open:opacity-100 group-data-open:blur-none group-data-open:[transition-delay:calc(var(--i)*55ms)] motion-reduce:blur-none motion-reduce:[transition-delay:0ms]">💬 Community</a>
<a href="#security" style="--i:4" class="flex items-center gap-2.5 rounded-[10px] px-3.5 py-2.5 text-[13.5px] font-medium text-tdd18-ink no-underline opacity-0 translate-y-1.5 blur-[6px] transition-[opacity,translate,filter,background] duration-300 hover:bg-tdd18-tint focus-visible:bg-tdd18-tint focus-visible:outline-none group-data-open:translate-y-0 group-data-open:opacity-100 group-data-open:blur-none group-data-open:[transition-delay:calc(var(--i)*55ms)] motion-reduce:blur-none motion-reduce:[transition-delay:0ms]">🔒 Security</a>
<div class="my-1 h-px bg-tdd18-edge" aria-hidden="true"></div>
<a href="#upgrade" style="--i:5" class="flex items-center gap-2.5 rounded-[10px] px-3.5 py-2.5 text-[13.5px] font-bold text-tdd18-acc no-underline opacity-0 translate-y-1.5 blur-[6px] transition-[opacity,translate,filter,background] duration-300 hover:bg-tdd18-tint focus-visible:bg-tdd18-tint focus-visible:outline-none group-data-open:translate-y-0 group-data-open:opacity-100 group-data-open:blur-none group-data-open:[transition-delay:calc(var(--i)*55ms)] motion-reduce:blur-none motion-reduce:[transition-delay:0ms]">⚡ Upgrade</a>
</div>
</div>
</nav>
</section>@import "tailwindcss";
@theme {
--color-tdd18-bg1: #faf5ff;
--color-tdd18-bg1: oklch(0.98 0.02 305);
--color-tdd18-bg2: #ede9fe;
--color-tdd18-bg2: oklch(0.94 0.03 295);
--color-tdd18-ink: #18181b;
--color-tdd18-ink: oklch(0.22 0.005 285);
--color-tdd18-edge: #e4e4e7;
--color-tdd18-edge: oklch(0.91 0.004 285);
--color-tdd18-tint: #f5f3ff;
--color-tdd18-tint: oklch(0.97 0.02 295);
--color-tdd18-acc: #7c3aed;
--color-tdd18-acc: oklch(0.54 0.24 295);
--color-tdd18-dot: #a78bfa;
--color-tdd18-dot: oklch(0.74 0.14 295);
--color-tdd18-dot2: #c4b5fd;
--color-tdd18-dot2: oklch(0.83 0.09 295);
--font-tdd18-sans: 'Space Grotesk', system-ui, sans-serif;
--ease-tdd18: cubic-bezier(0.34, 1.56, 0.64, 1);
}
.tdd-18 {
width: 100%;
min-height: 100svh;
}
.tdd-18 ::selection {
background: var(--color-tdd18-acc);
color: #ede9fe;
}@import "tailwindcss";
@theme {
--color-tdd18-bg1: #faf5ff;
--color-tdd18-bg1: oklch(0.98 0.02 305);
--color-tdd18-bg2: #ede9fe;
--color-tdd18-bg2: oklch(0.94 0.03 295);
--color-tdd18-ink: #18181b;
--color-tdd18-ink: oklch(0.22 0.005 285);
--color-tdd18-edge: #e4e4e7;
--color-tdd18-edge: oklch(0.91 0.004 285);
--color-tdd18-tint: #f5f3ff;
--color-tdd18-tint: oklch(0.97 0.02 295);
--color-tdd18-acc: #7c3aed;
--color-tdd18-acc: oklch(0.54 0.24 295);
--color-tdd18-dot: #a78bfa;
--color-tdd18-dot: oklch(0.74 0.14 295);
--color-tdd18-dot2: #c4b5fd;
--color-tdd18-dot2: oklch(0.83 0.09 295);
--font-tdd18-sans: 'Space Grotesk', system-ui, sans-serif;
--ease-tdd18: cubic-bezier(0.34, 1.56, 0.64, 1);
}
.tdd-18 {
width: 100%;
min-height: 100svh;
}
.tdd-18 ::selection {
background: var(--color-tdd18-acc);
color: #ede9fe;
}(function () {
document.querySelectorAll('.tdd-18').forEach(function (root) {
if (root.dataset.bound) return; root.dataset.bound = '1';
var wrap = root.querySelector('.group'),
btn = root.querySelector('#tdd18-btn');
if (!wrap || !btn) return;
function set(open) {
wrap.toggleAttribute('data-open', open);
btn.setAttribute('aria-expanded', String(open));
}
btn.addEventListener('click', function (e) {
e.stopPropagation();
set(btn.getAttribute('aria-expanded') !== 'true');
});
document.addEventListener('click', function (e) { if (!wrap.contains(e.target)) set(false); });
root.addEventListener('keydown', function (e) {
if (e.key === 'Escape' && wrap.hasAttribute('data-open')) { set(false); btn.focus(); }
});
});
})();(function () {
document.querySelectorAll('.tdd-18').forEach(function (root) {
if (root.dataset.bound) return; root.dataset.bound = '1';
var wrap = root.querySelector('.group'),
btn = root.querySelector('#tdd18-btn');
if (!wrap || !btn) return;
function set(open) {
wrap.toggleAttribute('data-open', open);
btn.setAttribute('aria-expanded', String(open));
}
btn.addEventListener('click', function (e) {
e.stopPropagation();
set(btn.getAttribute('aria-expanded') !== 'true');
});
document.addEventListener('click', function (e) { if (!wrap.contains(e.target)) set(false); });
root.addEventListener('keydown', function (e) {
if (e.key === 'Escape' && wrap.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-tdd18-bg1: #faf5ff;
--color-tdd18-bg1: oklch(0.98 0.02 305);
--color-tdd18-bg2: #ede9fe;
--color-tdd18-bg2: oklch(0.94 0.03 295);
--color-tdd18-ink: #18181b;
--color-tdd18-ink: oklch(0.22 0.005 285);
--color-tdd18-edge: #e4e4e7;
--color-tdd18-edge: oklch(0.91 0.004 285);
--color-tdd18-tint: #f5f3ff;
--color-tdd18-tint: oklch(0.97 0.02 295);
--color-tdd18-acc: #7c3aed;
--color-tdd18-acc: oklch(0.54 0.24 295);
--color-tdd18-dot: #a78bfa;
--color-tdd18-dot: oklch(0.74 0.14 295);
--color-tdd18-dot2: #c4b5fd;
--color-tdd18-dot2: oklch(0.83 0.09 295);
--font-tdd18-sans: 'Space Grotesk', system-ui, sans-serif;
--ease-tdd18: cubic-bezier(0.34, 1.56, 0.64, 1);
}
.tdd-18 {
width: 100%;
min-height: 100svh;
}
.tdd-18 ::selection {
background: var(--color-tdd18-acc);
color: #ede9fe;
}@import "tailwindcss";
@theme {
--color-tdd18-bg1: #faf5ff;
--color-tdd18-bg1: oklch(0.98 0.02 305);
--color-tdd18-bg2: #ede9fe;
--color-tdd18-bg2: oklch(0.94 0.03 295);
--color-tdd18-ink: #18181b;
--color-tdd18-ink: oklch(0.22 0.005 285);
--color-tdd18-edge: #e4e4e7;
--color-tdd18-edge: oklch(0.91 0.004 285);
--color-tdd18-tint: #f5f3ff;
--color-tdd18-tint: oklch(0.97 0.02 295);
--color-tdd18-acc: #7c3aed;
--color-tdd18-acc: oklch(0.54 0.24 295);
--color-tdd18-dot: #a78bfa;
--color-tdd18-dot: oklch(0.74 0.14 295);
--color-tdd18-dot2: #c4b5fd;
--color-tdd18-dot2: oklch(0.83 0.09 295);
--font-tdd18-sans: 'Space Grotesk', system-ui, sans-serif;
--ease-tdd18: cubic-bezier(0.34, 1.56, 0.64, 1);
}
.tdd-18 {
width: 100%;
min-height: 100svh;
}
.tdd-18 ::selection {
background: var(--color-tdd18-acc);
color: #ede9fe;
}<link rel="preconnect" href="https://fonts.googleapis.com"> <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin> <link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Space+Grotesk:wght@400;500;600;700&display=swap">
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Space+Grotesk:wght@400;500;600;700&display=swap">What changed in the port
Which parts became utilities, which stayed CSS, and why.
- The original's two JS loops (write delays on open, clear them on close) become one utility. That is the per-item index pattern paying for itself.
- The script is now four lines of state: toggle an attribute, mirror it into
aria-expanded. Nothing about the animation lives in JS. blur-noneis a real utility, so even the filter half of the effect needs no arbitrary value.- The panel uses
invisibleas well asopacity-0, closing the keyboard hole the CSS version left open.
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 Stagger Blur Entrance Dropdown
Source: https://codefronts.com/navigation/tailwind-dropdown-menus/tailwind-stagger-blur-entrance-dropdown/
Items that crystallise out of a frosted blur, one after another. The CSS version computes the stagger in JavaScript and writes inline transitionDelay on every item; here the delays are declarative — style="--i:3" plus one utility — and the script shrinks to a single attribute toggle.
## HTML
```html
<section class="tdd-18 w-full min-h-svh grid justify-center content-start bg-linear-[135deg,var(--color-tdd18-bg1),var(--color-tdd18-bg2)] font-tdd18-sans text-tdd18-ink px-5 py-9" aria-label="Stagger blur entrance dropdown demo">
<nav class="flex w-[min(480px,100%)] items-center justify-between rounded-2xl border border-tdd18-edge bg-white px-4 py-3 shadow-[0_4px_20px_oklch(0.54_0.24_295/0.1)]" aria-label="Primary">
<span class="text-lg font-bold tracking-[-0.5px] text-tdd18-acc">Specter</span>
<div class="group relative">
<button type="button" id="tdd18-btn" aria-expanded="false" aria-controls="tdd18-panel" class="flex min-h-11 cursor-pointer items-center gap-2 rounded-[10px] border-0 bg-tdd18-acc px-4.5 py-2 font-tdd18-sans text-sm font-semibold text-white transition-opacity duration-150 hover:opacity-90 focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-tdd18-acc aria-expanded:opacity-85">
Menu
<span class="size-2 rounded-full bg-tdd18-dot transition-[scale,background] duration-300 ease-tdd18 group-data-open:scale-150 group-data-open:bg-tdd18-dot2 motion-reduce:transition-none" aria-hidden="true"></span>
</button>
<div id="tdd18-panel" class="pointer-events-none invisible absolute top-[calc(100%+10px)] right-0 flex min-w-50 flex-col gap-0.5 rounded-2xl border border-tdd18-edge bg-white p-2 opacity-0 shadow-[0_12px_40px_oklch(0.54_0.24_295/0.18)] transition-[opacity,visibility] duration-200 group-data-open:pointer-events-auto group-data-open:visible group-data-open:opacity-100">
<a href="#launch" style="--i:0" class="flex items-center gap-2.5 rounded-[10px] px-3.5 py-2.5 text-[13.5px] font-medium text-tdd18-ink no-underline opacity-0 translate-y-1.5 blur-[6px] transition-[opacity,translate,filter,background] duration-300 hover:bg-tdd18-tint focus-visible:bg-tdd18-tint focus-visible:outline-none group-data-open:translate-y-0 group-data-open:opacity-100 group-data-open:blur-none group-data-open:[transition-delay:calc(var(--i)*55ms)] motion-reduce:blur-none motion-reduce:[transition-delay:0ms]">🚀 Launch</a>
<a href="#discover" style="--i:1" class="flex items-center gap-2.5 rounded-[10px] px-3.5 py-2.5 text-[13.5px] font-medium text-tdd18-ink no-underline opacity-0 translate-y-1.5 blur-[6px] transition-[opacity,translate,filter,background] duration-300 hover:bg-tdd18-tint focus-visible:bg-tdd18-tint focus-visible:outline-none group-data-open:translate-y-0 group-data-open:opacity-100 group-data-open:blur-none group-data-open:[transition-delay:calc(var(--i)*55ms)] motion-reduce:blur-none motion-reduce:[transition-delay:0ms]">🌟 Discover</a>
<a href="#metrics" style="--i:2" class="flex items-center gap-2.5 rounded-[10px] px-3.5 py-2.5 text-[13.5px] font-medium text-tdd18-ink no-underline opacity-0 translate-y-1.5 blur-[6px] transition-[opacity,translate,filter,background] duration-300 hover:bg-tdd18-tint focus-visible:bg-tdd18-tint focus-visible:outline-none group-data-open:translate-y-0 group-data-open:opacity-100 group-data-open:blur-none group-data-open:[transition-delay:calc(var(--i)*55ms)] motion-reduce:blur-none motion-reduce:[transition-delay:0ms]">📊 Metrics</a>
<a href="#community" style="--i:3" class="flex items-center gap-2.5 rounded-[10px] px-3.5 py-2.5 text-[13.5px] font-medium text-tdd18-ink no-underline opacity-0 translate-y-1.5 blur-[6px] transition-[opacity,translate,filter,background] duration-300 hover:bg-tdd18-tint focus-visible:bg-tdd18-tint focus-visible:outline-none group-data-open:translate-y-0 group-data-open:opacity-100 group-data-open:blur-none group-data-open:[transition-delay:calc(var(--i)*55ms)] motion-reduce:blur-none motion-reduce:[transition-delay:0ms]">💬 Community</a>
<a href="#security" style="--i:4" class="flex items-center gap-2.5 rounded-[10px] px-3.5 py-2.5 text-[13.5px] font-medium text-tdd18-ink no-underline opacity-0 translate-y-1.5 blur-[6px] transition-[opacity,translate,filter,background] duration-300 hover:bg-tdd18-tint focus-visible:bg-tdd18-tint focus-visible:outline-none group-data-open:translate-y-0 group-data-open:opacity-100 group-data-open:blur-none group-data-open:[transition-delay:calc(var(--i)*55ms)] motion-reduce:blur-none motion-reduce:[transition-delay:0ms]">🔒 Security</a>
<div class="my-1 h-px bg-tdd18-edge" aria-hidden="true"></div>
<a href="#upgrade" style="--i:5" class="flex items-center gap-2.5 rounded-[10px] px-3.5 py-2.5 text-[13.5px] font-bold text-tdd18-acc no-underline opacity-0 translate-y-1.5 blur-[6px] transition-[opacity,translate,filter,background] duration-300 hover:bg-tdd18-tint focus-visible:bg-tdd18-tint focus-visible:outline-none group-data-open:translate-y-0 group-data-open:opacity-100 group-data-open:blur-none group-data-open:[transition-delay:calc(var(--i)*55ms)] motion-reduce:blur-none motion-reduce:[transition-delay:0ms]">⚡ Upgrade</a>
</div>
</div>
</nav>
</section>
```
## CSS
```css
@import "tailwindcss";
@theme {
--color-tdd18-bg1: #faf5ff;
--color-tdd18-bg1: oklch(0.98 0.02 305);
--color-tdd18-bg2: #ede9fe;
--color-tdd18-bg2: oklch(0.94 0.03 295);
--color-tdd18-ink: #18181b;
--color-tdd18-ink: oklch(0.22 0.005 285);
--color-tdd18-edge: #e4e4e7;
--color-tdd18-edge: oklch(0.91 0.004 285);
--color-tdd18-tint: #f5f3ff;
--color-tdd18-tint: oklch(0.97 0.02 295);
--color-tdd18-acc: #7c3aed;
--color-tdd18-acc: oklch(0.54 0.24 295);
--color-tdd18-dot: #a78bfa;
--color-tdd18-dot: oklch(0.74 0.14 295);
--color-tdd18-dot2: #c4b5fd;
--color-tdd18-dot2: oklch(0.83 0.09 295);
--font-tdd18-sans: 'Space Grotesk', system-ui, sans-serif;
--ease-tdd18: cubic-bezier(0.34, 1.56, 0.64, 1);
}
.tdd-18 {
width: 100%;
min-height: 100svh;
}
.tdd-18 ::selection {
background: var(--color-tdd18-acc);
color: #ede9fe;
}
```
## JavaScript
```js
(function () {
document.querySelectorAll('.tdd-18').forEach(function (root) {
if (root.dataset.bound) return; root.dataset.bound = '1';
var wrap = root.querySelector('.group'),
btn = root.querySelector('#tdd18-btn');
if (!wrap || !btn) return;
function set(open) {
wrap.toggleAttribute('data-open', open);
btn.setAttribute('aria-expanded', String(open));
}
btn.addEventListener('click', function (e) {
e.stopPropagation();
set(btn.getAttribute('aria-expanded') !== 'true');
});
document.addEventListener('click', function (e) { if (!wrap.contains(e.target)) set(false); });
root.addEventListener('keydown', function (e) {
if (e.key === 'Escape' && wrap.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 Stagger Blur Entrance Dropdown
Source: https://codefronts.com/navigation/tailwind-dropdown-menus/tailwind-stagger-blur-entrance-dropdown/
Items that crystallise out of a frosted blur, one after another. The CSS version computes the stagger in JavaScript and writes inline transitionDelay on every item; here the delays are declarative — style="--i:3" plus one utility — and the script shrinks to a single attribute toggle.
## HTML
```html
<section class="tdd-18 w-full min-h-svh grid justify-center content-start bg-linear-[135deg,var(--color-tdd18-bg1),var(--color-tdd18-bg2)] font-tdd18-sans text-tdd18-ink px-5 py-9" aria-label="Stagger blur entrance dropdown demo">
<nav class="flex w-[min(480px,100%)] items-center justify-between rounded-2xl border border-tdd18-edge bg-white px-4 py-3 shadow-[0_4px_20px_oklch(0.54_0.24_295/0.1)]" aria-label="Primary">
<span class="text-lg font-bold tracking-[-0.5px] text-tdd18-acc">Specter</span>
<div class="group relative">
<button type="button" id="tdd18-btn" aria-expanded="false" aria-controls="tdd18-panel" class="flex min-h-11 cursor-pointer items-center gap-2 rounded-[10px] border-0 bg-tdd18-acc px-4.5 py-2 font-tdd18-sans text-sm font-semibold text-white transition-opacity duration-150 hover:opacity-90 focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-tdd18-acc aria-expanded:opacity-85">
Menu
<span class="size-2 rounded-full bg-tdd18-dot transition-[scale,background] duration-300 ease-tdd18 group-data-open:scale-150 group-data-open:bg-tdd18-dot2 motion-reduce:transition-none" aria-hidden="true"></span>
</button>
<div id="tdd18-panel" class="pointer-events-none invisible absolute top-[calc(100%+10px)] right-0 flex min-w-50 flex-col gap-0.5 rounded-2xl border border-tdd18-edge bg-white p-2 opacity-0 shadow-[0_12px_40px_oklch(0.54_0.24_295/0.18)] transition-[opacity,visibility] duration-200 group-data-open:pointer-events-auto group-data-open:visible group-data-open:opacity-100">
<a href="#launch" style="--i:0" class="flex items-center gap-2.5 rounded-[10px] px-3.5 py-2.5 text-[13.5px] font-medium text-tdd18-ink no-underline opacity-0 translate-y-1.5 blur-[6px] transition-[opacity,translate,filter,background] duration-300 hover:bg-tdd18-tint focus-visible:bg-tdd18-tint focus-visible:outline-none group-data-open:translate-y-0 group-data-open:opacity-100 group-data-open:blur-none group-data-open:[transition-delay:calc(var(--i)*55ms)] motion-reduce:blur-none motion-reduce:[transition-delay:0ms]">🚀 Launch</a>
<a href="#discover" style="--i:1" class="flex items-center gap-2.5 rounded-[10px] px-3.5 py-2.5 text-[13.5px] font-medium text-tdd18-ink no-underline opacity-0 translate-y-1.5 blur-[6px] transition-[opacity,translate,filter,background] duration-300 hover:bg-tdd18-tint focus-visible:bg-tdd18-tint focus-visible:outline-none group-data-open:translate-y-0 group-data-open:opacity-100 group-data-open:blur-none group-data-open:[transition-delay:calc(var(--i)*55ms)] motion-reduce:blur-none motion-reduce:[transition-delay:0ms]">🌟 Discover</a>
<a href="#metrics" style="--i:2" class="flex items-center gap-2.5 rounded-[10px] px-3.5 py-2.5 text-[13.5px] font-medium text-tdd18-ink no-underline opacity-0 translate-y-1.5 blur-[6px] transition-[opacity,translate,filter,background] duration-300 hover:bg-tdd18-tint focus-visible:bg-tdd18-tint focus-visible:outline-none group-data-open:translate-y-0 group-data-open:opacity-100 group-data-open:blur-none group-data-open:[transition-delay:calc(var(--i)*55ms)] motion-reduce:blur-none motion-reduce:[transition-delay:0ms]">📊 Metrics</a>
<a href="#community" style="--i:3" class="flex items-center gap-2.5 rounded-[10px] px-3.5 py-2.5 text-[13.5px] font-medium text-tdd18-ink no-underline opacity-0 translate-y-1.5 blur-[6px] transition-[opacity,translate,filter,background] duration-300 hover:bg-tdd18-tint focus-visible:bg-tdd18-tint focus-visible:outline-none group-data-open:translate-y-0 group-data-open:opacity-100 group-data-open:blur-none group-data-open:[transition-delay:calc(var(--i)*55ms)] motion-reduce:blur-none motion-reduce:[transition-delay:0ms]">💬 Community</a>
<a href="#security" style="--i:4" class="flex items-center gap-2.5 rounded-[10px] px-3.5 py-2.5 text-[13.5px] font-medium text-tdd18-ink no-underline opacity-0 translate-y-1.5 blur-[6px] transition-[opacity,translate,filter,background] duration-300 hover:bg-tdd18-tint focus-visible:bg-tdd18-tint focus-visible:outline-none group-data-open:translate-y-0 group-data-open:opacity-100 group-data-open:blur-none group-data-open:[transition-delay:calc(var(--i)*55ms)] motion-reduce:blur-none motion-reduce:[transition-delay:0ms]">🔒 Security</a>
<div class="my-1 h-px bg-tdd18-edge" aria-hidden="true"></div>
<a href="#upgrade" style="--i:5" class="flex items-center gap-2.5 rounded-[10px] px-3.5 py-2.5 text-[13.5px] font-bold text-tdd18-acc no-underline opacity-0 translate-y-1.5 blur-[6px] transition-[opacity,translate,filter,background] duration-300 hover:bg-tdd18-tint focus-visible:bg-tdd18-tint focus-visible:outline-none group-data-open:translate-y-0 group-data-open:opacity-100 group-data-open:blur-none group-data-open:[transition-delay:calc(var(--i)*55ms)] motion-reduce:blur-none motion-reduce:[transition-delay:0ms]">⚡ Upgrade</a>
</div>
</div>
</nav>
</section>
```
## CSS
```css
@import "tailwindcss";
@theme {
--color-tdd18-bg1: #faf5ff;
--color-tdd18-bg1: oklch(0.98 0.02 305);
--color-tdd18-bg2: #ede9fe;
--color-tdd18-bg2: oklch(0.94 0.03 295);
--color-tdd18-ink: #18181b;
--color-tdd18-ink: oklch(0.22 0.005 285);
--color-tdd18-edge: #e4e4e7;
--color-tdd18-edge: oklch(0.91 0.004 285);
--color-tdd18-tint: #f5f3ff;
--color-tdd18-tint: oklch(0.97 0.02 295);
--color-tdd18-acc: #7c3aed;
--color-tdd18-acc: oklch(0.54 0.24 295);
--color-tdd18-dot: #a78bfa;
--color-tdd18-dot: oklch(0.74 0.14 295);
--color-tdd18-dot2: #c4b5fd;
--color-tdd18-dot2: oklch(0.83 0.09 295);
--font-tdd18-sans: 'Space Grotesk', system-ui, sans-serif;
--ease-tdd18: cubic-bezier(0.34, 1.56, 0.64, 1);
}
.tdd-18 {
width: 100%;
min-height: 100svh;
}
.tdd-18 ::selection {
background: var(--color-tdd18-acc);
color: #ede9fe;
}
```
## JavaScript
```js
(function () {
document.querySelectorAll('.tdd-18').forEach(function (root) {
if (root.dataset.bound) return; root.dataset.bound = '1';
var wrap = root.querySelector('.group'),
btn = root.querySelector('#tdd18-btn');
if (!wrap || !btn) return;
function set(open) {
wrap.toggleAttribute('data-open', open);
btn.setAttribute('aria-expanded', String(open));
}
btn.addEventListener('click', function (e) {
e.stopPropagation();
set(btn.getAttribute('aria-expanded') !== 'true');
});
document.addEventListener('click', function (e) { if (!wrap.contains(e.target)) set(false); });
root.addEventListener('keydown', function (e) {
if (e.key === 'Escape' && wrap.hasAttribute('data-open')) { set(false); btn.focus(); }
});
});
})();
```How this works
The delays stop being JavaScript. The original loops the items on init and again on close to clear inline styles. Declaring the delay as a utility that reads --i deletes both loops and the cleanup bug that comes with them.
<a style="--i:3" class="opacity-0 blur-[6px] translate-y-1.5
group-data-open:opacity-100 group-data-open:blur-none
group-data-open:[transition-delay:calc(var(--i)*55ms)]">Closing is deliberately un-staggered, because the delay only exists in the open half — which is also what the original tried to achieve by clearing inline styles at close time.
Blur is expensive. Six blurred elements animating at once is fine; sixty is not. Keep the list short, which is good menu design anyway.
Make it yours
- Intensity:
blur-[6px]→blur-[12px]for a heavier crystallise. - Tempo: the
55msmultiplier. - Direction: add
-translate-x-2instead oftranslate-y-1.5for a side entrance. - Squeeze: add
scale-y-95 group-data-open:scale-y-100on the panel for a subtle stretch under the cascade.
Gotchas — read before shipping
- Many simultaneous
filter: blur()elements force GPU work; under about ten items it is free, above that it is not. - Delays declared in the base class list make the close staggered too, which reads as lag.
- Safari can flash a light edge as blur resolves on white; a hair of starting opacity avoids it.
group-data-open:requires thegroupand thedata-openattribute to be on the SAME element.
Browser support
| Chrome | Safari | Firefox | Edge |
|---|---|---|---|
| 111+ | 16.4+ | 128+ | 111+ |
CSS filter transitions are Baseline; Safari has hardware-accelerated filter animation since 12.