Mega Menu Panel — Free HTML CSS JS Navigation Snippet

Mega Menu Panel · Navigation · Plain HTML, CSS & JS · Live preview

Share & Support

What's included

Features

Full-width link grid
Links are shown as a multi-column grid of icon + title + description cells, far more scannable than a plain list.
Featured promo panel
A fixed gradient card spotlights a launch or guide beside the links, the way large product sites do.
One panel, data-driven
A single panel repaints from a MENUS object per top-level item, keeping the DOM light and the menu easy to extend.
Hover-intent timing
A 160ms close delay, cleared when the pointer enters the panel, keeps the menu open across the diagonal trigger-to-panel move.
Click and keyboard support
Triggers are clickable (with stopPropagation) and Escape closes the menu, so it is not hover-only.
composedPath outside-click
Outside-click detection uses e.composedPath() so it survives the panel repainting its contents.
Animated reveal
The panel fades and slides down with pointer-events off while hidden so it never blocks the page.
Responsive stacking
Under 720px the panel becomes single-column and the grid stacks for mobile.

About this UI Snippet

Mega Menu Panel — Full-Width Dropdown with Link Grid and Featured Promo

Screenshot of the Mega Menu Panel snippet rendered live

When a site has more than a handful of destinations, a plain dropdown becomes a long, hard-to-scan list. The mega menu solves this: a full-width panel that drops from the navigation bar with links organised into a grid — each with an icon, title, and description — plus a featured promo panel to spotlight what is new. It is the navigation pattern used by Stripe, GitHub, Atlassian, and most large product sites. This component builds a complete mega menu in HTML, CSS, and vanilla JavaScript, with hover-intent open, click and keyboard support, and a data-driven panel that swaps content per top-level item.

One shared panel, swapped per menu

Rather than a separate dropdown per nav item, there is one .mmp-panel whose content is repainted when you open a different menu. A MENUS object holds the data for each top-level item ("products", "solutions") — an array of grid cells and a feature promo. Opening a menu calls paint(), which builds the cell grid and the featured panel from that data. This keeps the DOM light (one panel, not many) and makes the menu trivially extensible: add a key to MENUS and a trigger with a matching data-menu attribute.

The two-zone layout

The panel is a grid with a flexible multi-column link area on the left (1fr) and a fixed 260px feature panel on the right. The link area is itself a two-column grid of cells, each a flex row with a tinted icon tile (coloured from a --c custom property via color-mix), a bold title, and a muted description — the scannable, explained-links format that makes a mega menu more useful than a bare list. The feature panel is a gradient card with a tag, headline, and link, anchoring the eye and giving you a place to promote a launch or a guide.

Hover-intent open and close

Mega menus that open and slam shut on every stray mouse movement are infuriating. This one uses hover intent: entering a nav item opens its menu immediately, but leaving does not close instantly — a 160ms setTimeout delays the close, and that timer is cleared if the pointer enters the panel (or another trigger) in the meantime. So moving diagonally from the trigger down into the panel keeps it open, while genuinely leaving closes it after a brief grace period. This forgiving timing is the difference between a mega menu that feels smooth and one that feels hostile.

Click and keyboard too

The menu is not hover-only, which would exclude touch and keyboard users. Each trigger is also clickable — clicking toggles its menu open or closed — and the trigger uses stopPropagation so its click does not immediately hit the document handler that closes the menu on outside clicks. That outside-click handler uses e.composedPath().includes(nav) to reliably detect clicks outside the whole nav even as the panel's contents are repainted, and Escape closes the menu from anywhere. Triggers carry aria-haspopup and aria-expanded that flips with state.

The reveal animation and chevron

The panel starts hidden with opacity: 0, translateY(-10px), and pointer-events: none; opening transitions it to visible and nudges it down into place. Because pointer-events are off while closed, the invisible panel never blocks clicks on the page behind it. The active trigger recolours to the accent and its chevron rotates 180 degrees, so it is always clear which menu is open.

Customisation

Edit the MENUS object to define each panel's cells (icon path, colour, title, description) and feature promo (gradient, tag, headline, link). Add a top-level item by adding a <li data-menu="key"> trigger and a MENUS.key entry. Swap the #6366f1 accent and the feature gradients for your brand. On screens under 720px the panel becomes single-column and the grid stacks, so the same menu works on mobile (where you would typically trigger it by click).

Build with AI

Build, Understand, Optimize, and Extend It With AI

You do not need to reconstruct the single-shared-panel architecture by inspecting the DOM alone. Paste this snippet's HTML, CSS, and JS into an AI coding assistant like Claude and ask it to explain exactly why there is one mmpPanel element repainted by paint(openKey) rather than one panel per top-level nav item, and how the 160ms scheduleClose timer combined with clearTimeout on the panel's own mouseenter creates the hover bridge that prevents flicker when the cursor moves diagonally from trigger to panel. The same assistant can help optimize it, for instance asking whether rebuilding the entire grid.innerHTML string on every openMenu call is wasteful compared to caching each menu's rendered HTML the first time it's painted. It is also useful for extending the menu: ask it to add arrow-key navigation between the cells inside an open panel, support a third or fourth top-level mega menu by extending the MENUS object, or make the panel width responsive to the number of cells rather than a fixed 260px feature column. Treat the code less like a finished artifact and more like a starting point for a conversation.

Prompt to recreate it

Copy this into your AI assistant of choice to build the effect from scratch, or as a jumping-off point for your own variant:

text
Build a "mega menu" navigation bar in plain HTML, CSS, and JavaScript with no libraries, using one shared dropdown panel repainted per top-level menu item rather than one panel per item.

Requirements:
- A nav bar with a brand mark, several top-level items where at least two are buttons with aria-haspopup and aria-expanded attributes (identified by a data-menu key), plus a single shared panel element positioned to span the nav.
- A data object keyed by each menu's identifier, where each entry defines an array of link "cells" (icon, accent color, title, description) and a single featured promo block (background, tag, title, link text).
- A paint function that, given a menu key, rebuilds the shared panel's link grid and featured promo entirely from that key's data, so opening a different top-level item swaps the panel's content without creating or destroying any panel DOM nodes.
- Opening a menu must work on both mouseenter (immediate) and click (toggle), and the panel must visually track which trigger is active by recoloring it and rotating its chevron icon.
- Closing on mouseleave must not happen instantly: leaving a trigger or the panel itself must schedule a close after a short delay (roughly 150-200ms), and entering either the panel or any trigger during that delay must cancel the pending close, so moving the cursor diagonally from the trigger down into the panel never causes a flicker.
- A document-level click listener must close the open menu when a click lands outside the whole nav (using a technique that correctly detects "outside" even though the panel's contents are being repainted), and a keydown listener must close the menu on Escape from anywhere on the page.
- The closed panel must be invisible and non-interactive (no pointer events) so it never blocks clicks on the page content beneath it, and the open panel must animate in with a fade and a slight vertical shift.

Want to tighten it up first? Run this prompt through the AI Prompt Studio to score it across 8 quality dimensions, catch anti-patterns, and tune the wording for Claude, ChatGPT, or Gemini before you paste it in.

Step by step

How to Use

  1. 1
    Paste the HTML, CSS, and JSA nav bar renders with brand, top-level links (Products, Solutions have dropdowns), and a Get started CTA.
  2. 2
    Hover Products or SolutionsA full-width panel drops down with a grid of explained links and a gradient feature promo, and the trigger's chevron rotates.
  3. 3
    Move into the panelHover intent keeps it open as you move from the trigger into the panel; leaving entirely closes it after a short grace period.
  4. 4
    Click or press EscapeClicking a trigger toggles its menu; clicking outside the nav or pressing Escape closes it.
  5. 5
    Edit the menusChange the MENUS object's cells and feature promo per key, and add items via a data-menu trigger plus a matching MENUS entry.
  6. 6
    Theme itSwap the accent colour and the feature gradients, and resize-test: under 720px the panel stacks to one column.

Real-world uses

Common Use Cases

Product and SaaS navigation
Organise many destinations into scannable groups with a featured callout — pair with a mega footer for the bottom of the page.
E-commerce category menus
Show product categories and a promoted collection in one panel; compare with a mega menu variant.
Documentation and developer sites
Group products, solutions, and resources with descriptions so visitors find the right section fast.
Enterprise and agency sites
Present solutions-by-industry and use-case grids with a guide promo, the way large B2B sites do.
Marketing site headers
Replace a cramped dropdown with an organised panel; complements a fullscreen menu for mobile.
Learning mega-menu UX
A reference for hover-intent timing, data-driven panel swapping, and accessible click/keyboard dropdown behaviour.

Got questions?

Frequently Asked Questions

Leaving a nav item does not close the menu immediately — it starts a 160ms setTimeout to close. If the pointer enters the panel (or another trigger) within that window, the timer is cleared and the menu stays open. This handles the common case of moving diagonally from the trigger down into the panel, where the cursor briefly leaves the trigger. Without the delay, that movement would close the menu before you reached it.

Add a <li class="mmp-item" data-menu="resources"> with a trigger button to the nav, then add a matching resources key to the MENUS object with its cells array and feature promo. The script wires every .mmp-item[data-menu] automatically and paints from MENUS[key], so no other code changes are needed — the new menu opens, paints, and closes like the others.

Yes. It is not hover-only: each trigger is clickable and toggles its menu, so touch users can tap to open. The trigger uses stopPropagation so its tap does not immediately trigger the outside-click close. Escape closes the menu, triggers carry aria-haspopup and aria-expanded, and on mobile (under 720px) the panel stacks to one column. For full keyboard menu navigation you can add arrow-key handling between cells.

A single panel that repaints its contents keeps the DOM lightweight (one node, not one per top-level item) and means the open/close animation and positioning logic exist once. The paint() function swaps in the right menu's cells and feature from the MENUS data when you open it. This is more maintainable and scales better than duplicating panel markup for every menu.

Store openKey in state and render the panel's cells/feature from a MENUS map keyed by it. Triggers set openKey on click and on mouseenter; mouseleave starts a close timeout you keep in a ref and clear on the panel's mouseenter. Add a document click listener (outside the nav) and an Escape handler in an effect, cleaned up on unmount. Bind .open and aria-expanded to openKey comparisons. The CSS — layout, reveal, color-mix icons — ports unchanged.