22 CSS Dropdown Menu Designs 21 / 22
Tab Panel Dropdown
A dropdown that contains a full tabbed interface inside it, letting users switch between content panels without leaving the nav.
The code
<div class="dd-21">
<link href="https://fonts.googleapis.com/css2?family=Plus+Jakarta+Sans:wght@400;500;600;700&display=swap" rel="stylesheet">
<nav class="dd-21__nav">
<span class="dd-21__brand">◈ Mosaic</span>
<div class="dd-21__items">
<div class="dd-21__item">
<button class="dd-21__trigger" id="dd-21-btn" aria-expanded="false">
Explore ▾
</button>
<div class="dd-21__drop" id="dd-21-drop">
<div class="dd-21__tabs" role="tablist" aria-label="Explore sections">
<button class="dd-21__tab is-active" role="tab" aria-selected="true" data-panel="dd-21-p1">Popular</button>
<button class="dd-21__tab" role="tab" aria-selected="false" data-panel="dd-21-p2">New</button>
<button class="dd-21__tab" role="tab" aria-selected="false" data-panel="dd-21-p3">Topics</button>
</div>
<div class="dd-21__panels">
<div class="dd-21__panel" id="dd-21-p1" role="tabpanel">
<a href="#" class="dd-21__plink">🔥 Most Visited</a>
<a href="#" class="dd-21__plink">🌟 Editor Picks</a>
<a href="#" class="dd-21__plink">📊 Trending Now</a>
<a href="#" class="dd-21__plink">🏆 All-Time Best</a>
</div>
<div class="dd-21__panel is-hidden" id="dd-21-p2" role="tabpanel">
<a href="#" class="dd-21__plink">🚀 Just Launched</a>
<a href="#" class="dd-21__plink">🕐 This Week</a>
<a href="#" class="dd-21__plink">📅 This Month</a>
<a href="#" class="dd-21__plink">🆕 Coming Soon</a>
</div>
<div class="dd-21__panel is-hidden" id="dd-21-p3" role="tabpanel">
<a href="#" class="dd-21__plink">🌟 Design</a>
<a href="#" class="dd-21__plink">💻 Engineering</a>
<a href="#" class="dd-21__plink">🚀 Product</a>
<a href="#" class="dd-21__plink">📚 Business</a>
</div>
</div>
</div>
</div>
<a href="#" class="dd-21__plain">Pricing</a>
<a href="#" class="dd-21__plain">Blog</a>
</div>
</nav>
</div> <div class="dd-21">
<link href="https://fonts.googleapis.com/css2?family=Plus+Jakarta+Sans:wght@400;500;600;700&display=swap" rel="stylesheet">
<nav class="dd-21__nav">
<span class="dd-21__brand">◈ Mosaic</span>
<div class="dd-21__items">
<div class="dd-21__item">
<button class="dd-21__trigger" id="dd-21-btn" aria-expanded="false">
Explore ▾
</button>
<div class="dd-21__drop" id="dd-21-drop">
<div class="dd-21__tabs" role="tablist" aria-label="Explore sections">
<button class="dd-21__tab is-active" role="tab" aria-selected="true" data-panel="dd-21-p1">Popular</button>
<button class="dd-21__tab" role="tab" aria-selected="false" data-panel="dd-21-p2">New</button>
<button class="dd-21__tab" role="tab" aria-selected="false" data-panel="dd-21-p3">Topics</button>
</div>
<div class="dd-21__panels">
<div class="dd-21__panel" id="dd-21-p1" role="tabpanel">
<a href="#" class="dd-21__plink">🔥 Most Visited</a>
<a href="#" class="dd-21__plink">🌟 Editor Picks</a>
<a href="#" class="dd-21__plink">📊 Trending Now</a>
<a href="#" class="dd-21__plink">🏆 All-Time Best</a>
</div>
<div class="dd-21__panel is-hidden" id="dd-21-p2" role="tabpanel">
<a href="#" class="dd-21__plink">🚀 Just Launched</a>
<a href="#" class="dd-21__plink">🕐 This Week</a>
<a href="#" class="dd-21__plink">📅 This Month</a>
<a href="#" class="dd-21__plink">🆕 Coming Soon</a>
</div>
<div class="dd-21__panel is-hidden" id="dd-21-p3" role="tabpanel">
<a href="#" class="dd-21__plink">🌟 Design</a>
<a href="#" class="dd-21__plink">💻 Engineering</a>
<a href="#" class="dd-21__plink">🚀 Product</a>
<a href="#" class="dd-21__plink">📚 Business</a>
</div>
</div>
</div>
</div>
<a href="#" class="dd-21__plain">Pricing</a>
<a href="#" class="dd-21__plain">Blog</a>
</div>
</nav>
</div>.dd-21, .dd-21 *, .dd-21 *::before, .dd-21 *::after {
margin: 0; padding: 0; box-sizing: border-box;
}
.dd-21 ::selection { background: #10b981; color: #fff; }
.dd-21 {
--brand: #10b981;
--surface: #fff;
--text: #064e3b;
--muted: #6b7280;
--border: #d1fae5;
--hover: #ecfdf5;
font-family: 'Plus Jakarta Sans', sans-serif;
min-height: 380px;
display: flex;
align-items: flex-start;
justify-content: center;
padding: 32px 20px;
background: linear-gradient(135deg, #ecfdf5 0%, #d1fae5 100%);
}
.dd-21__nav {
display: flex;
align-items: center;
gap: 4px;
background: var(--surface);
border: 1px solid var(--border);
border-radius: 14px;
padding: 10px 10px 10px 20px;
box-shadow: 0 4px 24px rgba(16,185,129,.12);
position: relative;
z-index: 100;
width: 100%;
max-width: 600px;
}
.dd-21__brand { font-size: 17px; font-weight: 700; color: var(--brand); margin-right: 12px; }
.dd-21__items { display: flex; align-items: center; gap: 4px; }
.dd-21__item { position: relative; }
.dd-21__trigger {
padding: 8px 14px;
border: none;
background: none;
cursor: pointer;
font-family: inherit;
font-size: 14px;
font-weight: 600;
color: var(--text);
border-radius: 8px;
transition: background 0.15s;
}
.dd-21__trigger:hover { background: var(--hover); }
.dd-21__trigger[aria-expanded="true"] { background: var(--hover); color: var(--brand); }
.dd-21__plain {
padding: 8px 14px;
color: var(--muted);
text-decoration: none;
font-size: 14px;
font-weight: 500;
border-radius: 8px;
transition: background 0.15s, color 0.15s;
}
.dd-21__plain:hover { background: var(--hover); color: var(--text); }
.dd-21__drop {
position: absolute;
top: calc(100% + 10px);
left: 0;
width: 260px;
background: var(--surface);
border: 1px solid var(--border);
border-radius: 14px;
box-shadow: 0 12px 40px rgba(16,185,129,.14);
overflow: hidden;
opacity: 0;
pointer-events: none;
transform: translateY(-8px);
transition: opacity 0.22s ease, transform 0.28s cubic-bezier(0.16, 1, 0.3, 1);
}
.dd-21__drop.is-open { opacity: 1; pointer-events: auto; transform: translateY(0); }
.dd-21__tabs {
display: flex;
border-bottom: 1px solid var(--border);
padding: 6px 6px 0;
gap: 2px;
}
.dd-21__tab {
flex: 1;
padding: 8px 6px;
border: none;
border-radius: 8px 8px 0 0;
background: transparent;
cursor: pointer;
font-family: inherit;
font-size: 13px;
font-weight: 600;
color: var(--muted);
border-bottom: 2px solid transparent;
transition: color 0.15s, background 0.15s;
position: relative;
bottom: -1px;
}
.dd-21__tab:hover { color: var(--text); background: #f0fdf4; }
.dd-21__tab.is-active { color: var(--brand); border-bottom-color: var(--brand); background: #f0fdf4; }
.dd-21__panels { padding: 6px; min-height: 140px; }
.dd-21__panel { display: flex; flex-direction: column; gap: 2px; }
.dd-21__panel.is-hidden { display: none; }
@keyframes dd-21-fadein {
from { opacity: 0; transform: translateY(4px); }
to { opacity: 1; transform: translateY(0); }
}
.dd-21__panel:not(.is-hidden) { animation: dd-21-fadein 0.22s ease; }
.dd-21__plink {
display: flex;
align-items: center;
gap: 8px;
padding: 9px 12px;
border-radius: 9px;
text-decoration: none;
color: var(--text);
font-size: 13.5px;
font-weight: 500;
transition: background 0.12s;
}
.dd-21__plink:hover { background: var(--hover); color: var(--brand); }
@media (prefers-reduced-motion: reduce) {
.dd-21__drop, .dd-21__tab, .dd-21__panel { transition: none; animation: none; }
} .dd-21, .dd-21 *, .dd-21 *::before, .dd-21 *::after {
margin: 0; padding: 0; box-sizing: border-box;
}
.dd-21 ::selection { background: #10b981; color: #fff; }
.dd-21 {
--brand: #10b981;
--surface: #fff;
--text: #064e3b;
--muted: #6b7280;
--border: #d1fae5;
--hover: #ecfdf5;
font-family: 'Plus Jakarta Sans', sans-serif;
min-height: 380px;
display: flex;
align-items: flex-start;
justify-content: center;
padding: 32px 20px;
background: linear-gradient(135deg, #ecfdf5 0%, #d1fae5 100%);
}
.dd-21__nav {
display: flex;
align-items: center;
gap: 4px;
background: var(--surface);
border: 1px solid var(--border);
border-radius: 14px;
padding: 10px 10px 10px 20px;
box-shadow: 0 4px 24px rgba(16,185,129,.12);
position: relative;
z-index: 100;
width: 100%;
max-width: 600px;
}
.dd-21__brand { font-size: 17px; font-weight: 700; color: var(--brand); margin-right: 12px; }
.dd-21__items { display: flex; align-items: center; gap: 4px; }
.dd-21__item { position: relative; }
.dd-21__trigger {
padding: 8px 14px;
border: none;
background: none;
cursor: pointer;
font-family: inherit;
font-size: 14px;
font-weight: 600;
color: var(--text);
border-radius: 8px;
transition: background 0.15s;
}
.dd-21__trigger:hover { background: var(--hover); }
.dd-21__trigger[aria-expanded="true"] { background: var(--hover); color: var(--brand); }
.dd-21__plain {
padding: 8px 14px;
color: var(--muted);
text-decoration: none;
font-size: 14px;
font-weight: 500;
border-radius: 8px;
transition: background 0.15s, color 0.15s;
}
.dd-21__plain:hover { background: var(--hover); color: var(--text); }
.dd-21__drop {
position: absolute;
top: calc(100% + 10px);
left: 0;
width: 260px;
background: var(--surface);
border: 1px solid var(--border);
border-radius: 14px;
box-shadow: 0 12px 40px rgba(16,185,129,.14);
overflow: hidden;
opacity: 0;
pointer-events: none;
transform: translateY(-8px);
transition: opacity 0.22s ease, transform 0.28s cubic-bezier(0.16, 1, 0.3, 1);
}
.dd-21__drop.is-open { opacity: 1; pointer-events: auto; transform: translateY(0); }
.dd-21__tabs {
display: flex;
border-bottom: 1px solid var(--border);
padding: 6px 6px 0;
gap: 2px;
}
.dd-21__tab {
flex: 1;
padding: 8px 6px;
border: none;
border-radius: 8px 8px 0 0;
background: transparent;
cursor: pointer;
font-family: inherit;
font-size: 13px;
font-weight: 600;
color: var(--muted);
border-bottom: 2px solid transparent;
transition: color 0.15s, background 0.15s;
position: relative;
bottom: -1px;
}
.dd-21__tab:hover { color: var(--text); background: #f0fdf4; }
.dd-21__tab.is-active { color: var(--brand); border-bottom-color: var(--brand); background: #f0fdf4; }
.dd-21__panels { padding: 6px; min-height: 140px; }
.dd-21__panel { display: flex; flex-direction: column; gap: 2px; }
.dd-21__panel.is-hidden { display: none; }
@keyframes dd-21-fadein {
from { opacity: 0; transform: translateY(4px); }
to { opacity: 1; transform: translateY(0); }
}
.dd-21__panel:not(.is-hidden) { animation: dd-21-fadein 0.22s ease; }
.dd-21__plink {
display: flex;
align-items: center;
gap: 8px;
padding: 9px 12px;
border-radius: 9px;
text-decoration: none;
color: var(--text);
font-size: 13.5px;
font-weight: 500;
transition: background 0.12s;
}
.dd-21__plink:hover { background: var(--hover); color: var(--brand); }
@media (prefers-reduced-motion: reduce) {
.dd-21__drop, .dd-21__tab, .dd-21__panel { transition: none; animation: none; }
}(function() {
var btn = document.getElementById('dd-21-btn');
var drop = document.getElementById('dd-21-drop');
if (!btn || !drop) return;
var tabs = Array.from(drop.querySelectorAll('.dd-21__tab'));
var panels = Array.from(drop.querySelectorAll('.dd-21__panel'));
function activateTab(tab) {
tabs.forEach(function(t) { t.classList.remove('is-active'); t.setAttribute('aria-selected', 'false'); });
panels.forEach(function(p) { p.classList.add('is-hidden'); });
tab.classList.add('is-active');
tab.setAttribute('aria-selected', 'true');
var target = document.getElementById(tab.dataset.panel);
if (target) target.classList.remove('is-hidden');
}
tabs.forEach(function(tab) { tab.addEventListener('click', function() { activateTab(tab); }); });
btn.addEventListener('click', function(e) {
e.stopPropagation();
var open = drop.classList.toggle('is-open');
btn.setAttribute('aria-expanded', open ? 'true' : 'false');
});
document.addEventListener('click', function(e) {
if (!drop.contains(e.target) && e.target !== btn) {
drop.classList.remove('is-open');
btn.setAttribute('aria-expanded', 'false');
}
});
document.addEventListener('keydown', function(e) {
if (e.key === 'Escape') { drop.classList.remove('is-open'); btn.setAttribute('aria-expanded', 'false'); }
});
})(); (function() {
var btn = document.getElementById('dd-21-btn');
var drop = document.getElementById('dd-21-drop');
if (!btn || !drop) return;
var tabs = Array.from(drop.querySelectorAll('.dd-21__tab'));
var panels = Array.from(drop.querySelectorAll('.dd-21__panel'));
function activateTab(tab) {
tabs.forEach(function(t) { t.classList.remove('is-active'); t.setAttribute('aria-selected', 'false'); });
panels.forEach(function(p) { p.classList.add('is-hidden'); });
tab.classList.add('is-active');
tab.setAttribute('aria-selected', 'true');
var target = document.getElementById(tab.dataset.panel);
if (target) target.classList.remove('is-hidden');
}
tabs.forEach(function(tab) { tab.addEventListener('click', function() { activateTab(tab); }); });
btn.addEventListener('click', function(e) {
e.stopPropagation();
var open = drop.classList.toggle('is-open');
btn.setAttribute('aria-expanded', open ? 'true' : 'false');
});
document.addEventListener('click', function(e) {
if (!drop.contains(e.target) && e.target !== btn) {
drop.classList.remove('is-open');
btn.setAttribute('aria-expanded', 'false');
}
});
document.addEventListener('keydown', function(e) {
if (e.key === 'Escape') { drop.classList.remove('is-open'); btn.setAttribute('aria-expanded', 'false'); }
});
})();How this works
The dropdown panel contains a tab bar (.dd-21__tabs) and a panel area (.dd-21__panels). JavaScript attaches click listeners to each tab button. On click, all tabs lose is-active, the clicked tab gains it, all panels get the is-hidden class, and the target panel (matched by data-panel → id) becomes visible with a fade-in animation.
The dropdown itself opens/closes by toggling an is-open class on the panel, triggered by a button click. An aria-selected attribute is toggled on tabs for accessibility. The role="tablist", role="tab", and role="tabpanel" ARIA pattern is applied so screen readers understand the tabbed widget inside the dropdown.
Customize
- Make tabs scrollable for many tabs by adding
overflow-x: auto; white-space: nowrapto the tab bar — useful for mobile-width panels. - Add a tab indicator line that slides between tabs using a JS-measured
leftandwidthon a singledivelement. - Persist the active tab across dropdown open/close sessions using a variable to track the last active tab index.
- Add icons above each tab label for a richer visual hierarchy inside the dropdown.
Watch out for
- Dropdown panels with dynamic content height can cause layout jumps — set a
min-heighton the panel container to prevent collapse when switching to shorter tabs. - Tab keyboard navigation (ArrowLeft/Right between tabs) is part of the ARIA tab pattern — without it, keyboard users must Tab through all content instead of using arrow keys.
- If the dropdown is inside an ancestor with
overflow: hidden, the absolute-positioned panel will be clipped — test in your actual layout.
Browser support
| Chrome | Safari | Firefox | Edge |
|---|---|---|---|
| 49+ | 10+ | 44+ | 49+ |
Fully supported in all modern browsers; ARIA tab pattern announced by all major screen readers.