
An animated dropdown mega menu that animates menu items when switching between nav links. Inspired by Stripe.com’s header navigation.
How to use it:
1. Code the HTML for the Dropdown Mega Menu.
<header>
<img src="./images/logo.svg" alt="Stripe Logo" />
<nav class="navbar">
<ul class="nav__links">
<li data-expand="products" class="nav--link">Products</li>
<li data-expand="use-cases" class="nav--link">Use Cases</li>
</ul>
</nav>
<div class="tip"></div>
<section class="header__expandMenu">
<div class="menu__container">
<div id="products">
<div class="sub__menu">
<h3 class="title">PAYMENTS</h3>
<ul class="subMenu__items">
<li class="subMenu--item">
<img src="./images/payment.svg" alt="" />
<span class="label__container">
<div class="label">
Payments
<img
class="right--arrow"
src="./images/right-arrow.svg"
alt=""
/>
</div>
<div class="label--desc">Online payments</div>
</span>
</li>
<li class="subMenu--item">
<img src="./images/terminal.svg" alt="" />
<span class="label__container">
<div class="label">
Terminal
<img
class="right--arrow"
src="./images/right-arrow.svg"
alt=""
/>
</div>
<div class="label--desc">In-person payments</div>
</span>
</li>
<li class="subMenu--item">
<img src="./images/connect.svg" alt="" />
<span class="label__container">
<div class="label">
Connect
<img
class="right--arrow"
src="./images/right-arrow.svg"
alt=""
/>
</div>
<div class="label--desc">Payments for platforms</div>
</span>
</li>
<li class="subMenu--item">
<img src="./images/billing.svg" alt="" />
<span class="label__container">
<div class="label">
Billing
<img
class="right--arrow"
src="./images/right-arrow.svg"
alt=""
/>
</div>
<div class="label--desc">Subscriptions & invoicing</div>
</span>
</li>
</ul>
</div>
<div class="sub__menu">
<h3 class="title">PAYOUTS</h3>
<ul class="subMenu__items">
<li class="subMenu--item">
<img src="./images/payouts.svg" alt="" />
<span class="label__container">
<div class="label">
Payouts
<img
class="right--arrow"
src="./images/right-arrow.svg"
alt=""
/>
</div>
<div class="label--desc">Programmatic payouts</div>
</span>
</li>
<li class="subMenu--item">
<img src="./images/issuing.svg" alt="" />
<span class="label__container">
<div class="label">
Issuing
<img
class="right--arrow"
src="./images/right-arrow.svg"
alt=""
/>
</div>
<div class="label--desc">Card creation</div>
</span>
</li>
</ul>
</div>
<div class="sub__menu">
<h3 class="title">BUISNESS OPERATIONS</h3>
<ul class="subMenu__items">
<li class="subMenu--item">
<img src="./images/radar.svg" alt="" />
<span class="label__container">
<div class="label">
Radar
<img
class="right--arrow"
src="./images/right-arrow.svg"
alt=""
/>
</div>
<div class="label--desc">Fraud & risk management</div>
</span>
</li>
<li class="subMenu--item">
<img src="./images/sigma.svg" alt="" />
<span class="label__container">
<div class="label">
Sigma
<img
class="right--arrow"
src="./images/right-arrow.svg"
alt=""
/>
</div>
<div class="label--desc">Custom reports</div>
</span>
</li>
<li class="subMenu--item">
<img src="./images/atlas.svg" alt="" />
<span class="label__container">
<div class="label">
Atlas
<img
class="right--arrow"
src="./images/right-arrow.svg"
alt=""
/>
</div>
<div class="label--desc">Start-up incorporation</div>
</span>
</li>
</ul>
</div>
</div>
<div id="use-cases">
<ul class="subMenu__items">
<li class="subMenu--item">
<img class="icon--production" src="./images/saas.svg" alt="" />
<span class="label__container">
<div class="label">
SaaS
<img
class="right--arrow"
src="./images/right-arrow.svg"
alt=""
/>
</div>
<div class="label--desc">
Manage recurring bills and subscriptions
</div>
</span>
</li>
<li class="subMenu--item">
<img
class="icon--production"
src="./images/marketplace.svg"
alt=""
/>
<span class="label__container">
<div class="label">
Marketplaces
<img
class="right--arrow"
src="./images/right-arrow.svg"
alt=""
/>
</div>
<div class="label--desc">
Pay out globally and facilitate multi-party payments
</div>
</span>
</li>
<li class="subMenu--item">
<img
class="icon--production"
src="./images/platform.svg"
alt=""
/>
<span class="label__container">
<div class="label">
Platform
<img
class="right--arrow"
src="./images/right-arrow.svg"
alt=""
/>
</div>
<div class="label--desc">
Let customers accept payments within your platform
</div>
</span>
</li>
</ul>
</div>
</div>
</section>
</header>2. The required CSS styles.
header {
display: flex;
padding: 1.5rem 3rem;
justify-content: space-around;
align-items: center;
}
.nav__links {
display: flex;
list-style: none;
color: #fff;
font-weight: 700;
}
.nav--link {
padding: 0 1rem;
transition: opacity 100ms linear;
cursor: pointer;
}
.btn {
padding: 0.5rem 1rem;
display: flex;
align-items: center;
font-family: inherit;
font-weight: 700;
color: #fff;
outline: none;
border: none;
background-color: #ffffff35;
border-radius: 2rem;
transition: background-color 100ms linear;
cursor: pointer;
}
.arrow {
width: 20px;
height: 10px;
position: relative;
transform: translateX(-4px);
}
.line {
position: absolute;
top: 46%;
right: 0;
height: 2px;
width: 7px;
background-color: #fff;
transform-origin: 100% 50%;
}
.arrow--sideUp {
transform: rotate(45deg);
}
.arrow--sideDown {
transform: rotate(-45deg);
}
.arrow--hoverLine {
width: 12px;
transform: scale(0);
}
.arrow,
.line {
transition: transform 100ms ease-in;
}
.btn--primary:hover {
background-color: #ffffff65;
}
.btn:hover .arrow {
transform: none;
}
.btn:hover .arrow--hoverLine {
transform: scale(1);
}
.tip {
width: 1.25rem;
height: 1.25rem;
background-color: #fff;
position: absolute;
top: 4.15rem;
left: 0;
clip-path: polygon(50% 0%, 100% 50%, 50% 100%, 0% 50%);
transition: transform 100ms linear;
opacity: 0;
}
.header__expandMenu {
position: absolute;
top: 4.5rem;
left: 50%;
width: 95%;
height: 90%;
transform-origin: 0%;
transform: translateX(-50%) rotate3d(1, 0, 0, -15deg);
background-color: white;
border-radius: 0.5rem;
perspective: 100px;
transition: width 250ms ease, height 250ms ease, opacity 150ms ease,
transform 200ms ease-in;
overflow: hidden;
opacity: 0;
pointer-events: none;
}
.menu__container {
width: 100%;
height: 100%;
background-color: white;
}
.menu__container > * {
position: absolute;
top: 0;
left: 50%;
padding: 2rem;
overflow: hidden;
transform: translateX(-35%);
transition: transform 250ms linear, opacity 250ms ease;
opacity: 0;
}
#products {
display: grid;
grid-template-columns: repeat(3, 300px);
}
.item--one {
grid-column: span 2;
}
#use-cases {
width: 450px;
}
.subMenu__items {
list-style: none;
}
.title {
font-size: 0.85rem;
margin-bottom: 1.75rem;
}
.subMenu--item {
display: flex;
align-items: center;
cursor: pointer;
}
.label__container {
margin-left: 0.75rem;
}
.label {
font-size: 0.9rem;
font-weight: 700;
color: rgba(0, 0, 73, 0.644);
}
.label--desc {
font-size: 0.9rem;
color: rgb(83, 83, 83);
transform: translateY(-3px);
transition: color 100ms ease;
}
.subMenu--item + .subMenu--item {
margin-top: 1.5rem;
}
.icon--production {
transform: translateY(-55%) scale(1.1);
}
.right--arrow {
width: 12px;
transform: translateY(1px) scale(0, 1);
transition: transform 150ms ease-in-out;
}
.subMenu--item:hover .right--arrow {
transform: translateY(1.75px) scale(1);
}
.subMenu--item:hover .label--desc {
color: black;
}
.active {
z-index: 1;
opacity: 1;
transform: translatex(-50%);
}
.prev {
transform: translateX(-65%);
}
.expand {
opacity: 1;
pointer-events: all;
transform: translateX(-50%) rotateX(0);
}
.hover {
opacity: 0.5;
}
.new--expand {
transition: opacity 150ms ease, transform 150ms ease-in;
}
.first {
transition: none;
}3. The main JavaScript to enable the dropdown mega menu.
const handleMouseEnter = (e) => {
if (!e.target.dataset.expand) {
return;
}
navsVisited += 1;
if (navsVisited === 1) {
expandMenu.classList.add("new--expand");
menus.forEach((menu) => menu.classList.add("first"));
indicator.classList.add("first");
} else {
expandMenu.classList.remove("new--expand");
menus.forEach((menu) => menu.classList.remove("first"));
indicator.classList.remove("first");
}
navLinks.forEach((navLink) => {
if (navLink === e.target) {
navLink.classList.add("hover");
currentNav = navLink;
} else {
navLink.classList.remove("hover");
}
});
const navLinkCenter = Math.floor(
e.target.offsetLeft + e.target.clientWidth / 2
);
indicator.style.transform = `translateX(${navLinkCenter}px)`;
indicator.style.opacity = "1";
const targetMenu = document.querySelector(`#${e.target.dataset.expand}`);
const targetCoords = targetMenu.getBoundingClientRect();
const { width: targetWidth, height: targetHeight } = targetCoords;
expandMenu.style.width = targetWidth + "px";
expandMenu.style.height = targetHeight + "px";
const prevMenu = targetMenu.previousElementSibling;
targetMenu.classList.remove("prev");
if (prevMenu) {
prevMenu.classList.add("prev");
}
menus.forEach((menu) => {
if (menu.id === targetMenu.id) {
menu.classList.add("active");
} else {
menu.classList.remove("active");
}
});
expandMenu.classList.add("expand");
};
const handleMouseLeave = (e) => {
if (isMouseOnMenu || e.y > 50) {
return;
}
forceInitialState();
};
const forceInitialState = () => {
expandMenu.classList.remove("expand", "active");
currentNav.classList.remove("hover");
menus.forEach((menu) => menu.removeAttribute("class"));
indicator.style.opacity = "0";
currentNav = null;
navsVisited = 0;
};
const expandMenu = document.querySelector(".header__expandMenu");
const menus = expandMenu.querySelectorAll(".menu__container > *");
const navLinks = document.querySelectorAll(".nav--link");
const indicator = document.querySelector(".tip");
let isMouseOnMenu = false;
let currentNav;
let navsVisited = 0;
const {
height: menuHeight,
width: menuWidth,
} = expandMenu.getBoundingClientRect();
navLinks.forEach((navLink) => {
navLink.addEventListener("mouseenter", handleMouseEnter);
});
expandMenu.addEventListener("mouseenter", () => {
if (expandMenu.style.opacity === "1") {
isMouseOnMenu = true;
}
});
expandMenu.addEventListener("mouseleave", (e) => {
if (e.y > 70) {
isMouseOnMenu = false;
forceInitialState();
}
});
document
.querySelector(".nav__links")
.addEventListener("mouseleave", handleMouseLeave);






