22 CSS Dropdown Menu Designs 18 / 22
Stagger Blur Entrance Dropdown
A JS-toggled dropdown where each menu item blurs in from a frosted state, with per-item transition delays applied programmatically for a cinematic cascade.
The code
<div class="dd-18">
<link href="https://fonts.googleapis.com/css2?family=Space+Grotesk:wght@400;500;600;700&display=swap" rel="stylesheet">
<div class="dd-18__scene">
<nav class="dd-18__nav">
<span class="dd-18__brand">Specter</span>
<div class="dd-18__group" id="dd-18-group">
<button class="dd-18__trigger" id="dd-18-btn" aria-expanded="false">
Menu
<span class="dd-18__dot" id="dd-18-dot"></span>
</button>
<div class="dd-18__panel" id="dd-18-panel">
<a href="#" class="dd-18__item">🚀 Launch</a>
<a href="#" class="dd-18__item">🌟 Discover</a>
<a href="#" class="dd-18__item">📊 Metrics</a>
<a href="#" class="dd-18__item">💬 Community</a>
<a href="#" class="dd-18__item">🔒 Security</a>
<div class="dd-18__sep"></div>
<a href="#" class="dd-18__item dd-18__item--em">⚡ Upgrade</a>
</div>
</div>
</nav>
</div>
</div> <div class="dd-18">
<link href="https://fonts.googleapis.com/css2?family=Space+Grotesk:wght@400;500;600;700&display=swap" rel="stylesheet">
<div class="dd-18__scene">
<nav class="dd-18__nav">
<span class="dd-18__brand">Specter</span>
<div class="dd-18__group" id="dd-18-group">
<button class="dd-18__trigger" id="dd-18-btn" aria-expanded="false">
Menu
<span class="dd-18__dot" id="dd-18-dot"></span>
</button>
<div class="dd-18__panel" id="dd-18-panel">
<a href="#" class="dd-18__item">🚀 Launch</a>
<a href="#" class="dd-18__item">🌟 Discover</a>
<a href="#" class="dd-18__item">📊 Metrics</a>
<a href="#" class="dd-18__item">💬 Community</a>
<a href="#" class="dd-18__item">🔒 Security</a>
<div class="dd-18__sep"></div>
<a href="#" class="dd-18__item dd-18__item--em">⚡ Upgrade</a>
</div>
</div>
</nav>
</div>
</div>.dd-18, .dd-18 *, .dd-18 *::before, .dd-18 *::after {
margin: 0; padding: 0; box-sizing: border-box;
}
.dd-18 ::selection { background: #7c3aed; color: #ede9fe; }
.dd-18 {
--brand: #7c3aed;
--surface: #fff;
--text: #18181b;
--muted: #71717a;
--border: #e4e4e7;
--hover: #f5f3ff;
font-family: 'Space Grotesk', sans-serif;
min-height: 380px;
display: flex;
align-items: flex-start;
justify-content: center;
padding: 36px 20px;
background: linear-gradient(135deg, #faf5ff 0%, #ede9fe 100%);
}
.dd-18__scene {
width: 100%;
max-width: 480px;
position: relative;
z-index: 100;
}
.dd-18__nav {
display: flex;
align-items: center;
justify-content: space-between;
background: var(--surface);
border: 1px solid var(--border);
border-radius: 14px;
padding: 12px 16px;
box-shadow: 0 4px 20px rgba(124,58,237,.1);
}
.dd-18__brand {
font-size: 18px;
font-weight: 700;
color: var(--brand);
letter-spacing: -0.5px;
}
.dd-18__group { position: relative; }
.dd-18__trigger {
display: flex;
align-items: center;
gap: 8px;
padding: 8px 18px;
background: var(--brand);
border: none;
border-radius: 10px;
cursor: pointer;
font-family: inherit;
font-size: 14px;
font-weight: 600;
color: #fff;
transition: opacity 0.15s;
}
.dd-18__trigger:hover { opacity: 0.9; }
.dd-18__trigger[aria-expanded="true"] { opacity: 0.85; }
.dd-18__dot {
width: 8px;
height: 8px;
border-radius: 50%;
background: #a78bfa;
transition: transform 0.3s cubic-bezier(0.34, 1.56, 0.64, 1);
}
.dd-18__trigger[aria-expanded="true"] .dd-18__dot {
transform: scale(1.5);
background: #c4b5fd;
}
.dd-18__panel {
position: absolute;
top: calc(100% + 10px);
right: 0;
min-width: 200px;
background: var(--surface);
border: 1px solid var(--border);
border-radius: 14px;
box-shadow: 0 12px 40px rgba(124,58,237,.18);
padding: 8px;
display: flex;
flex-direction: column;
gap: 2px;
opacity: 0;
pointer-events: none;
transition: opacity 0.2s ease;
}
.dd-18__panel.is-open {
opacity: 1;
pointer-events: auto;
}
.dd-18__item {
display: flex;
align-items: center;
gap: 10px;
padding: 10px 13px;
border-radius: 10px;
text-decoration: none;
color: var(--text);
font-size: 13.5px;
font-weight: 500;
opacity: 0;
filter: blur(6px);
transform: translateY(6px);
transition: opacity 0.3s ease, filter 0.3s ease, transform 0.3s ease, background 0.12s;
}
.dd-18__panel.is-open .dd-18__item {
opacity: 1;
filter: blur(0);
transform: translateY(0);
}
.dd-18__item:hover { background: var(--hover); }
.dd-18__item--em { color: var(--brand); font-weight: 700; }
.dd-18__sep { height: 1px; background: var(--border); margin: 4px 0; }
@media (prefers-reduced-motion: reduce) {
.dd-18__item, .dd-18__panel { transition: none; filter: none; }
.dd-18__panel.is-open .dd-18__item { opacity: 1; filter: none; transform: none; }
} .dd-18, .dd-18 *, .dd-18 *::before, .dd-18 *::after {
margin: 0; padding: 0; box-sizing: border-box;
}
.dd-18 ::selection { background: #7c3aed; color: #ede9fe; }
.dd-18 {
--brand: #7c3aed;
--surface: #fff;
--text: #18181b;
--muted: #71717a;
--border: #e4e4e7;
--hover: #f5f3ff;
font-family: 'Space Grotesk', sans-serif;
min-height: 380px;
display: flex;
align-items: flex-start;
justify-content: center;
padding: 36px 20px;
background: linear-gradient(135deg, #faf5ff 0%, #ede9fe 100%);
}
.dd-18__scene {
width: 100%;
max-width: 480px;
position: relative;
z-index: 100;
}
.dd-18__nav {
display: flex;
align-items: center;
justify-content: space-between;
background: var(--surface);
border: 1px solid var(--border);
border-radius: 14px;
padding: 12px 16px;
box-shadow: 0 4px 20px rgba(124,58,237,.1);
}
.dd-18__brand {
font-size: 18px;
font-weight: 700;
color: var(--brand);
letter-spacing: -0.5px;
}
.dd-18__group { position: relative; }
.dd-18__trigger {
display: flex;
align-items: center;
gap: 8px;
padding: 8px 18px;
background: var(--brand);
border: none;
border-radius: 10px;
cursor: pointer;
font-family: inherit;
font-size: 14px;
font-weight: 600;
color: #fff;
transition: opacity 0.15s;
}
.dd-18__trigger:hover { opacity: 0.9; }
.dd-18__trigger[aria-expanded="true"] { opacity: 0.85; }
.dd-18__dot {
width: 8px;
height: 8px;
border-radius: 50%;
background: #a78bfa;
transition: transform 0.3s cubic-bezier(0.34, 1.56, 0.64, 1);
}
.dd-18__trigger[aria-expanded="true"] .dd-18__dot {
transform: scale(1.5);
background: #c4b5fd;
}
.dd-18__panel {
position: absolute;
top: calc(100% + 10px);
right: 0;
min-width: 200px;
background: var(--surface);
border: 1px solid var(--border);
border-radius: 14px;
box-shadow: 0 12px 40px rgba(124,58,237,.18);
padding: 8px;
display: flex;
flex-direction: column;
gap: 2px;
opacity: 0;
pointer-events: none;
transition: opacity 0.2s ease;
}
.dd-18__panel.is-open {
opacity: 1;
pointer-events: auto;
}
.dd-18__item {
display: flex;
align-items: center;
gap: 10px;
padding: 10px 13px;
border-radius: 10px;
text-decoration: none;
color: var(--text);
font-size: 13.5px;
font-weight: 500;
opacity: 0;
filter: blur(6px);
transform: translateY(6px);
transition: opacity 0.3s ease, filter 0.3s ease, transform 0.3s ease, background 0.12s;
}
.dd-18__panel.is-open .dd-18__item {
opacity: 1;
filter: blur(0);
transform: translateY(0);
}
.dd-18__item:hover { background: var(--hover); }
.dd-18__item--em { color: var(--brand); font-weight: 700; }
.dd-18__sep { height: 1px; background: var(--border); margin: 4px 0; }
@media (prefers-reduced-motion: reduce) {
.dd-18__item, .dd-18__panel { transition: none; filter: none; }
.dd-18__panel.is-open .dd-18__item { opacity: 1; filter: none; transform: none; }
}(function() {
var btn = document.getElementById('dd-18-btn');
var panel = document.getElementById('dd-18-panel');
if (!btn || !panel) return;
var items = Array.from(panel.querySelectorAll('.dd-18__item'));
items.forEach(function(el, i) { el.dataset.delay = i * 55; });
function openPanel() {
panel.classList.add('is-open');
btn.setAttribute('aria-expanded', 'true');
items.forEach(function(el) { el.style.transitionDelay = el.dataset.delay + 'ms'; });
}
function closePanel() {
items.forEach(function(el) { el.style.transitionDelay = '0ms'; });
panel.classList.remove('is-open');
btn.setAttribute('aria-expanded', 'false');
}
btn.addEventListener('click', function(e) {
e.stopPropagation();
panel.classList.contains('is-open') ? closePanel() : openPanel();
});
document.addEventListener('click', function(e) {
if (!panel.contains(e.target) && e.target !== btn) closePanel();
});
document.addEventListener('keydown', function(e) {
if (e.key === 'Escape') closePanel();
});
})(); (function() {
var btn = document.getElementById('dd-18-btn');
var panel = document.getElementById('dd-18-panel');
if (!btn || !panel) return;
var items = Array.from(panel.querySelectorAll('.dd-18__item'));
items.forEach(function(el, i) { el.dataset.delay = i * 55; });
function openPanel() {
panel.classList.add('is-open');
btn.setAttribute('aria-expanded', 'true');
items.forEach(function(el) { el.style.transitionDelay = el.dataset.delay + 'ms'; });
}
function closePanel() {
items.forEach(function(el) { el.style.transitionDelay = '0ms'; });
panel.classList.remove('is-open');
btn.setAttribute('aria-expanded', 'false');
}
btn.addEventListener('click', function(e) {
e.stopPropagation();
panel.classList.contains('is-open') ? closePanel() : openPanel();
});
document.addEventListener('click', function(e) {
if (!panel.contains(e.target) && e.target !== btn) closePanel();
});
document.addEventListener('keydown', function(e) {
if (e.key === 'Escape') closePanel();
});
})();How this works
JavaScript adds an is-open class to the panel on trigger click. The panel itself uses opacity 0 → 1 and the individual items use opacity: 0; filter: blur(6px); transform: translateY(6px) as their default hidden state. Once is-open is on the parent, each item transitions to opacity: 1; filter: blur(0); transform: translateY(0).
The stagger is applied by the JS loop: items.forEach((el, i) => el.style.transitionDelay = (i * 55) + 'ms'). This runs once at init, setting inline delay values. Because the delays are inline styles, they take precedence over the stylesheet defaults, and the CSS transition automatically picks them up when the class changes. On close, the delays are cleared so all items fade out together quickly.
Customize
- Change the blur intensity by editing the default item style
filter: blur(6px)— increase to12pxfor a more dramatic crystallize effect. - Reverse the stagger on close by keeping the delays but reversing the direction: before removing
is-open, re-apply delays in reverse order. - Combine with a
scaleY(0.95) → scaleY(1)on the panel container for a slight squeeze that enhances the reveal feel. - Use
translate3d(0, 8px, 0)instead oftranslateYto hint at GPU compositing and ensure smooth rendering on low-power devices.
Watch out for
filter: blur()triggers GPU compositing — having many blurred elements simultaneously can cause frame drops on integrated graphics; keep the list short (under 10 items).- Inline
transitionDelaystyles set via JS persist even when the element is in the closed state — clear them (set to empty string) during the close transition to avoid close stagger. - The blur from 0 → visible causes a brief white flash in some Safari versions on light backgrounds — a tiny initial
opacity: 0.01can prevent this edge case.
Browser support
| Chrome | Safari | Firefox | Edge |
|---|---|---|---|
| 49+ | 12+ | 35+ | 49+ |
CSS filter blur is fully supported; Safari added hardware-accelerated filter transitions in v12.