Mega Menu — Free HTML CSS JS Dropdown Snippet

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

Share & Support

What's included

Features

Centred panel with transform trick
translateX(-50%) centres the panel below any trigger. Open state composes translateY and scale on the same transform property to avoid losing the centering.
CSS arrow pointer
::before pseudo-element rotated 45deg with matching border creates a standard dropdown arrow without extra markup.
Hover-intent timer guard
150ms setTimeout on mouseleave, cancelled by mouseenter on either element, prevents the flicker of crossing the gap between trigger and panel.
Click and keyboard toggle
Button click toggles the panel open/closed. Escape key closes it. Click-outside closes it via a document listener with .contains() check.
Gradient featured card
Fourth column uses a purple gradient card with semi-transparent white CTA button — adapts to any brand gradient without hardcoded colours.
ARIA attributes
aria-haspopup="true", aria-expanded toggled on open/close, and role="region" with aria-label on the panel for screen reader compatibility.
Three-column layout
CSS grid with four columns (3×1fr + 200px fixed) for the featured panel. Each column uses flex-direction column for natural link stacking.
Icon tiles on links
Each mega link has a small rounded icon tile with a custom tinted background. Swap emoji for SVG icons without changing layout.

About this UI Snippet

Mega Menu — HTML CSS JavaScript

Screenshot of the Mega Menu snippet rendered live

Desktop mega menu with 3 linked columns, featured card, hover and click open, arrow indicator, and Escape-to-close. Pure HTML/CSS/JS.

A mega menu is an expanded navigation dropdown that reveals multiple columns of categorised links, often with a featured promotional panel. It is the standard pattern for product-heavy SaaS sites, e-commerce stores, and enterprise dashboards where a simple one-level dropdown cannot surface enough destinations without overwhelming users. This snippet builds a full mega menu with three linked columns, a gradient featured card, a CSS arrow pointer, and combined hover + click behaviour — all in vanilla HTML, CSS, and JavaScript.

Panel positioning and the CSS arrow

The mega panel is position: absolute; left: 50%; transform: translateX(-50%) on the .has-mega nav item. This centres the panel below the trigger regardless of where the nav item sits in the bar. The open state composes two transforms on a single property: transform: translateX(-50%) translateY(0) scale(1) — the closed state uses translateX(-50%) translateY(-8px) scale(0.98). Both transforms must be written together or the translateX centering is lost when the other transforms change. The decorative arrow pointer is a pseudo-element ::before rotated 45° with the same border-left and border-top as the panel border, positioned absolutely above the panel top edge.

Hover-intent with timer guard

A plain mouseenter / mouseleave approach causes flickering as the mouse moves from the nav trigger across the 14px gap into the panel. The solution is a scheduleClose() function that sets a 150ms setTimeout on mouseleave. Both the trigger's parent <li> and the mega panel itself call clearTimeout on mouseenter, cancelling the pending close. This creates a "hover bridge" — the user can move the mouse across the gap without the panel closing mid-movement.

Dual open trigger (hover + click)

The trigger button also supports click-to-toggle, which is essential for keyboard users and touch devices where hover events do not fire reliably. The click handler calls e.stopPropagation() to prevent the document-level click listener from immediately closing a panel that was just opened. The document listener closes the panel when a click lands outside the .has-mega container, using .contains() to check ancestry.

Keyboard accessibility

An Escape keydown listener on the document always closes the panel regardless of focus position. The trigger button carries aria-haspopup="true" and aria-expanded which is toggled on every open/close. The mega div uses role="region" with aria-label="Products menu" so screen readers announce the region when focus enters.

Featured panel

The fourth column is a gradient card using background: linear-gradient(135deg, #6366f1, #8b5cf6) — the indigo-to-violet diagonal is a common SaaS brand treatment. The featured CTA button uses rgba(255,255,255,0.2) background so it adapts to any gradient colour behind it without needing a hardcoded contrasting colour. The width: fit-content on the CTA prevents it from stretching to full column width.

Step by step

How to Use

  1. 1
    Hover over "Products"The mega panel slides down with a scale-and-fade animation and a CSS arrow indicator points up to the trigger button.
  2. 2
    Browse the three columnsEach column has a category heading and three links with icon, name, and description. Hover each link for the background highlight.
  3. 3
    See the featured cardThe fourth column shows a gradient promotional card with a "New" badge, title, description, and a CTA button.
  4. 4
    Move mouse awayMoving the mouse off the panel or the trigger starts a 150ms close timer. Moving back into either cancels it — no accidental closes.
  5. 5
    Press EscapePressing Escape closes the panel from anywhere on the page, resetting the trigger's aria-expanded to false.
  6. 6
    Add more mega menusDuplicate the .has-mega <li> structure for other nav items. Each needs its own trigger, mega div, and JS listener wired to separate element IDs.

Real-world uses

Common Use Cases

SaaS product sites
Expose product lines, features, and integrations in one dropdown. Pair with a sticky header so the nav remains accessible on long landing pages.
E-commerce category nav
Show top-level departments and subcategories with preview images. Combine with a chip filter on the category page for further filtering.
Enterprise dashboards
Organise tools and modules into a mega menu so users can navigate between sections without going back to a home screen.
Documentation sites
Surface API sections, guides, and reference pages grouped by topic. Add a search input as a fifth column for instant doc search.
Agency and portfolio sites
Show service categories and case studies. Link the featured card to a recent project. Combine with animated tabs for the main page content.

Got questions?

Frequently Asked Questions

Duplicate the .has-mega <li> with a new id on both the trigger button and the mega div. Add a second set of open/close event listeners in JS referencing the new IDs. Each mega menu is fully independent.

On mobile, hide .mega and replace with an off-canvas drawer or accordion. Use a media query to switch the .has-mega from position:relative + hover behaviour to a full-width collapsible panel on small screens.

CSS transform is a single property — setting transform in one rule overwrites any previously set transform values. If the open state only sets translateY(0) scale(1), it loses the translateX(-50%) centering from the base rule. All transforms must be written together.

Fetch your navigation data on page load, then generate the .mega-inner HTML using a template literal map over the response data. Re-attach event listeners after innerHTML is set, or use event delegation with a single listener on .mega-inner.

Listen for ArrowDown on the trigger to move focus into the first mega link. Then listen for ArrowDown/ArrowUp on .mega-link elements to move between them with element.nextElementSibling?.focus(). Tab naturally moves focus forward through links.

Yes. Export it as a React, Vue, or Angular component with the buttons above the preview. The hover-to-open dropdown and the multi-column panel grid are pure CSS, so they port over unchanged; the only JavaScript — the click-outside close and the keyboard focus handling — moves into a useEffect (React), onMounted (Vue), or ngAfterViewInit (Angular) lifecycle hook so listeners attach after the menu mounts. The link data is a natural fit for an array you map over with JSX, v-for, or *ngFor. The Tailwind export rewrites the mega-panel grid, spacing, and hover states as utility classes for a Tailwind project.