UI Components Medium
Mega Menu
Full-width multi-column dropdown navigation menu with categories, links, icons, and a featured section.
Open in Lab
MCP
vanilla-js css
Targets: JS HTML
Code
*,
*::before,
*::after {
box-sizing: border-box;
margin: 0;
padding: 0;
}
:root {
--bg: #050910;
--card: #0d1117;
--text: #f2f6ff;
--muted: #475569;
--border: rgba(255, 255, 255, 0.08);
--accent: #38bdf8;
--nav-h: 60px;
--ease: cubic-bezier(0.4, 0, 0.2, 1);
}
body {
font-family: Inter, system-ui, sans-serif;
background: var(--bg);
color: var(--text);
min-height: 100vh;
}
/* ── Navbar ── */
.navbar {
position: fixed;
top: 0;
left: 0;
right: 0;
z-index: 200;
background: rgba(5, 9, 16, 0.8);
border-bottom: 1px solid var(--border);
backdrop-filter: blur(18px);
-webkit-backdrop-filter: blur(18px);
}
.navbar__inner {
max-width: 1100px;
margin: 0 auto;
height: var(--nav-h);
display: flex;
align-items: center;
gap: 1.5rem;
padding: 0 1.5rem;
}
/* Logo */
.navbar__logo {
display: flex;
align-items: center;
gap: 0.4rem;
text-decoration: none;
color: var(--text);
font-weight: 700;
font-size: 1rem;
flex-shrink: 0;
}
.logo-gem {
color: var(--accent);
}
/* Nav */
.navbar__nav {
flex: 1;
display: flex;
align-items: center;
gap: 0.25rem;
}
.nav-link {
padding: 0.4rem 0.875rem;
font-size: 0.875rem;
font-weight: 500;
color: var(--muted);
text-decoration: none;
border-radius: 6px;
transition: color 0.18s, background 0.18s;
}
.nav-link:hover {
color: var(--text);
background: rgba(255, 255, 255, 0.04);
}
.nav-item-wrap {
position: static;
}
.nav-trigger {
padding: 0.4rem 0.875rem;
font-size: 0.875rem;
font-weight: 500;
color: var(--muted);
background: none;
border: none;
border-radius: 6px;
cursor: pointer;
display: inline-flex;
align-items: center;
gap: 0.3rem;
transition: color 0.18s, background 0.18s;
white-space: nowrap;
}
.nav-trigger:hover,
.nav-trigger[aria-expanded="true"] {
color: var(--text);
background: rgba(255, 255, 255, 0.04);
}
.trigger-chevron {
flex-shrink: 0;
transition: transform 0.22s var(--ease);
}
.nav-trigger[aria-expanded="true"] .trigger-chevron {
transform: rotate(180deg);
}
.navbar__cta {
margin-left: auto;
flex-shrink: 0;
padding: 0.4rem 1.1rem;
background: var(--accent);
color: #050910;
font-size: 0.875rem;
font-weight: 600;
text-decoration: none;
border-radius: 999px;
transition: opacity 0.18s;
}
.navbar__cta:hover {
opacity: 0.85;
}
/* ── Mega Panel ── */
.mega-panel {
position: absolute;
top: var(--nav-h);
left: 0;
right: 0;
background: var(--card);
border-bottom: 1px solid var(--border);
box-shadow: 0 24px 64px rgba(0, 0, 0, 0.5);
padding: 2rem 0;
opacity: 0;
pointer-events: none;
transform: translateY(-8px);
transition: opacity 0.22s var(--ease), transform 0.22s var(--ease);
z-index: 100;
}
.mega-panel.open {
opacity: 1;
pointer-events: all;
transform: translateY(0);
}
.mega-panel__inner {
max-width: 1100px;
margin: 0 auto;
padding: 0 1.5rem;
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 2rem;
}
.mega-panel__inner--2col {
grid-template-columns: repeat(2, 1fr);
max-width: 640px;
}
/* ── Column ── */
.mega-col {
display: flex;
flex-direction: column;
gap: 0.25rem;
}
.mega-col__title {
font-size: 0.68rem;
font-weight: 700;
letter-spacing: 0.1em;
text-transform: uppercase;
color: var(--muted);
margin-bottom: 0.625rem;
}
/* ── Mega link with icon ── */
.mega-link {
display: flex;
align-items: flex-start;
gap: 0.75rem;
padding: 0.625rem 0.75rem;
border-radius: 8px;
text-decoration: none;
color: var(--text);
transition: background 0.18s;
font-size: 0.875rem;
}
.mega-link:hover {
background: rgba(255, 255, 255, 0.05);
}
.mega-link strong {
display: block;
font-weight: 600;
margin-bottom: 0.125rem;
}
.mega-link__icon {
font-size: 1.1rem;
width: 30px;
height: 30px;
background: rgba(56, 189, 248, 0.08);
border-radius: 7px;
display: grid;
place-items: center;
flex-shrink: 0;
margin-top: 1px;
}
.mega-link__desc {
display: block;
font-size: 0.78rem;
color: var(--muted);
line-height: 1.4;
font-weight: 400;
}
/* Plain links (no icon) */
.mega-link--plain {
padding: 0.5rem 0.75rem;
font-size: 0.875rem;
color: var(--muted);
gap: 0;
}
.mega-link--plain:hover {
color: var(--text);
}
/* ── Featured column ── */
.mega-col--featured {
}
.mega-featured-card {
display: flex;
flex-direction: column;
gap: 0.5rem;
padding: 1.25rem;
border-radius: 12px;
background: linear-gradient(135deg, rgba(56, 189, 248, 0.08) 0%, rgba(56, 189, 248, 0.03) 100%);
border: 1px solid rgba(56, 189, 248, 0.15);
text-decoration: none;
color: var(--text);
transition: border-color 0.2s, background 0.2s;
position: relative;
}
.mega-featured-card:hover {
border-color: rgba(56, 189, 248, 0.35);
background: linear-gradient(135deg, rgba(56, 189, 248, 0.12) 0%, rgba(56, 189, 248, 0.06) 100%);
}
.featured-card__badge {
position: absolute;
top: 0.875rem;
right: 0.875rem;
background: var(--accent);
color: #050910;
font-size: 0.65rem;
font-weight: 700;
padding: 0.15rem 0.5rem;
border-radius: 999px;
text-transform: uppercase;
letter-spacing: 0.06em;
}
.featured-card__icon {
font-size: 1.75rem;
margin-bottom: 0.25rem;
}
.featured-card__title {
font-size: 0.9375rem;
font-weight: 700;
}
.featured-card__desc {
font-size: 0.8rem;
color: var(--muted);
line-height: 1.55;
}
.featured-card__cta {
margin-top: 0.25rem;
font-size: 0.8125rem;
font-weight: 600;
color: var(--accent);
}
/* ── Overlay ── */
.menu-overlay {
position: fixed;
inset: 0;
z-index: 50;
display: none;
}
.menu-overlay.active {
display: block;
}
/* ── Page body ── */
.page-body {
padding-top: calc(var(--nav-h) + 5rem);
min-height: 100vh;
display: flex;
align-items: flex-start;
justify-content: center;
}
.page-hero {
text-align: center;
max-width: 480px;
padding: 2rem;
}
.page-hero__title {
font-size: 2.25rem;
font-weight: 800;
letter-spacing: -0.03em;
margin-bottom: 1rem;
}
.page-hero__desc {
font-size: 0.95rem;
color: var(--muted);
line-height: 1.7;
}
.page-hero__desc strong {
color: var(--text);
}(function () {
var triggers = document.querySelectorAll(".nav-trigger");
var overlay = document.getElementById("menu-overlay");
var activePanel = null;
var activeTrigger = null;
function openMenu(trigger) {
var panelId = trigger.getAttribute("aria-controls");
var panel = document.getElementById(panelId);
if (!panel) return;
// Close any currently open menu first
if (activePanel && activePanel !== panel) {
closeMenu();
}
trigger.setAttribute("aria-expanded", "true");
panel.classList.add("open");
if (overlay) overlay.classList.add("active");
activePanel = panel;
activeTrigger = trigger;
}
function closeMenu() {
if (activeTrigger) activeTrigger.setAttribute("aria-expanded", "false");
if (activePanel) activePanel.classList.remove("open");
if (overlay) overlay.classList.remove("active");
activePanel = null;
activeTrigger = null;
}
// Toggle on trigger click
triggers.forEach(function (trigger) {
trigger.addEventListener("click", function () {
var panelId = trigger.getAttribute("aria-controls");
var panel = document.getElementById(panelId);
if (panel && panel.classList.contains("open")) {
closeMenu();
} else {
openMenu(trigger);
}
});
// Keyboard: Enter/Space handled natively for buttons
trigger.addEventListener("keydown", function (e) {
if (e.key === "Escape") {
closeMenu();
trigger.focus();
}
});
});
// Close on overlay click
if (overlay) {
overlay.addEventListener("click", closeMenu);
}
// Close on Escape from anywhere
document.addEventListener("keydown", function (e) {
if (e.key === "Escape" && activePanel) {
var prev = activeTrigger;
closeMenu();
if (prev) prev.focus();
}
});
// Close when focus leaves the open panel and its trigger
document.addEventListener("focusin", function (e) {
if (!activePanel) return;
var inNavbar = document.querySelector(".navbar").contains(e.target);
if (!inNavbar) closeMenu();
});
})();<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Mega Menu</title>
<link rel="stylesheet" href="style.css" />
</head>
<body>
<!-- ── Navbar ── -->
<header class="navbar" id="navbar">
<div class="navbar__inner">
<a href="#" class="navbar__logo" aria-label="Home">
<span class="logo-gem" aria-hidden="true">✦</span> Stealthis
</a>
<nav class="navbar__nav" aria-label="Main navigation">
<a href="#" class="nav-link">Home</a>
<!-- Products trigger -->
<div class="nav-item-wrap">
<button
class="nav-trigger"
aria-haspopup="true"
aria-expanded="false"
aria-controls="menu-products"
id="trigger-products"
>
Products
<svg class="trigger-chevron" aria-hidden="true" width="12" height="12" viewBox="0 0 12 12" fill="none">
<path d="M2 4l4 4 4-4" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
</svg>
</button>
</div>
<!-- Resources trigger -->
<div class="nav-item-wrap">
<button
class="nav-trigger"
aria-haspopup="true"
aria-expanded="false"
aria-controls="menu-resources"
id="trigger-resources"
>
Resources
<svg class="trigger-chevron" aria-hidden="true" width="12" height="12" viewBox="0 0 12 12" fill="none">
<path d="M2 4l4 4 4-4" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
</svg>
</button>
</div>
<a href="#" class="nav-link">Pricing</a>
</nav>
<a href="#" class="navbar__cta">Get started</a>
</div>
<!-- ── Products mega-menu ── -->
<div class="mega-panel" id="menu-products" role="region" aria-label="Products menu">
<div class="mega-panel__inner">
<!-- Column 1: UI Components -->
<div class="mega-col">
<p class="mega-col__title">UI Components</p>
<a href="#" class="mega-link">
<span class="mega-link__icon" aria-hidden="true">🧩</span>
<span>
<strong>Components</strong>
<span class="mega-link__desc">50+ copy-paste HTML components</span>
</span>
</a>
<a href="#" class="mega-link">
<span class="mega-link__icon" aria-hidden="true">🎨</span>
<span>
<strong>Animations</strong>
<span class="mega-link__desc">GSAP, CSS, and Three.js motion</span>
</span>
</a>
<a href="#" class="mega-link">
<span class="mega-link__icon" aria-hidden="true">🃏</span>
<span>
<strong>Cards & Layouts</strong>
<span class="mega-link__desc">Grid systems, card patterns, heroes</span>
</span>
</a>
</div>
<!-- Column 2: Developer Tools -->
<div class="mega-col">
<p class="mega-col__title">Developer Tools</p>
<a href="#" class="mega-link">
<span class="mega-link__icon" aria-hidden="true">🔧</span>
<span>
<strong>MCP Server</strong>
<span class="mega-link__desc">Access resources via Claude MCP</span>
</span>
</a>
<a href="#" class="mega-link">
<span class="mega-link__icon" aria-hidden="true">📦</span>
<span>
<strong>Boilerplates</strong>
<span class="mega-link__desc">Astro, Next.js, Vite starters</span>
</span>
</a>
<a href="#" class="mega-link">
<span class="mega-link__icon" aria-hidden="true">⚡</span>
<span>
<strong>Snippets</strong>
<span class="mega-link__desc">Utility patterns for everyday use</span>
</span>
</a>
</div>
<!-- Column 3: Featured -->
<div class="mega-col mega-col--featured">
<p class="mega-col__title">Featured</p>
<a href="#" class="mega-featured-card">
<div class="featured-card__badge">New</div>
<div class="featured-card__icon" aria-hidden="true">🚀</div>
<strong class="featured-card__title">Lab Demos</strong>
<p class="featured-card__desc">Full-screen interactive demos — copy the complete code in one click.</p>
<span class="featured-card__cta">Explore the lab →</span>
</a>
</div>
</div>
</div>
<!-- ── Resources mega-menu ── -->
<div class="mega-panel" id="menu-resources" role="region" aria-label="Resources menu">
<div class="mega-panel__inner mega-panel__inner--2col">
<div class="mega-col">
<p class="mega-col__title">Learn</p>
<a href="#" class="mega-link mega-link--plain">Documentation</a>
<a href="#" class="mega-link mega-link--plain">Getting Started Guide</a>
<a href="#" class="mega-link mega-link--plain">Changelog</a>
<a href="#" class="mega-link mega-link--plain">Video Tutorials</a>
</div>
<div class="mega-col">
<p class="mega-col__title">Community</p>
<a href="#" class="mega-link mega-link--plain">GitHub</a>
<a href="#" class="mega-link mega-link--plain">Discord</a>
<a href="#" class="mega-link mega-link--plain">Showcase</a>
<a href="#" class="mega-link mega-link--plain">Blog</a>
</div>
</div>
</div>
</header>
<!-- Overlay (click-away to close) -->
<div class="menu-overlay" id="menu-overlay" aria-hidden="true"></div>
<!-- Page content -->
<main class="page-body">
<div class="page-hero">
<h1 class="page-hero__title">Mega Menu</h1>
<p class="page-hero__desc">Click <strong>Products</strong> or <strong>Resources</strong> in the navbar above to open the multi-column dropdown.</p>
</div>
</main>
<script src="script.js"></script>
</body>
</html>Mega Menu
A full-width multi-column dropdown for top-level navigation with grouped links, section icons, and a highlighted featured card. No dependencies.
Features
- Fixed top navbar with three top-level items
- “Products” opens a 3-column mega menu with icon links and a featured card
- “Resources” opens a 2-column menu with grouped link lists
- Smooth fade + slide-down animation on open
- Closes on outside click,
Escape, or when another trigger is activated - Full keyboard navigation:
Tabthrough items,Enter/Spaceto open,Escapeto close
How it works
- Each trigger button sets
aria-expandedand toggles an.openclass on its associated panel - Panels are
position: fixedbelow the navbar, spanning the full width, hidden viaopacity: 0 + pointer-events: noneuntil.open - An overlay
<div>catches outside clicks to close the active menu Escapekey closes any open menu and returns focus to its trigger
Accessibility
- Nav landmark with
aria-label - Trigger buttons use
aria-haspopup="true"andaria-expanded - Mega panel has
role="region"andaria-label - All links are keyboard-reachable in DOM order