Author: | naveen-27 |
---|---|
Views Total: | 3,134 views |
Official Page: | Go to website |
Last Update: | December 30, 2020 |
License: | MIT |
Preview:

Description:
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);