Skip to content

Instantly share code, notes, and snippets.

@mucavel
Created October 10, 2024 14:02
Show Gist options
  • Save mucavel/937c7d10063002968eca9340c9b76919 to your computer and use it in GitHub Desktop.
Save mucavel/937c7d10063002968eca9340c9b76919 to your computer and use it in GitHub Desktop.
Megamenu - Bootstrap 4
<nav class="megamenu">
<ul class="megamenu-nav d-flex justify-content-center" role="menu">
<li class="nav-item">
<a class="nav-link" href="#">
<i class="fa fa-home"></i>
<span class="sr-only">Home</span>
</a>
</li>
<li class="nav-item is-parent">
<a class="nav-link" href="#" id="megamenu-dropdown-1" aria-haspopup="true" aria-expanded="false">
Link 1 <i class="fa fa-angle-down"></i>
</a>
<div class="megamenu-content" aria-labelledby="megamenu-dropdown-1">
<div class="container">
<div class="row">
<div class="col-8 pr-5">
<div class="row">
<div class="col-6">
<h3 class="">Another title</h3>
<hr>
<ul class="subnav">
<li class="subnav-item">
<a href="#" class="subnav-link">Menuitem 1</a>
</li>
<li class="subnav-item">
<a href="#" class="subnav-link">Another menuitem</a>
</li>
<li class="subnav-item">
<a href="#" class="subnav-link">Menuitem 3</a>
</li>
<li class="subnav-item">
<a href="#" class="subnav-link">Menuitem 1</a>
</li>
<li class="subnav-item">
<a href="#" class="subnav-link">Another menuitem</a>
</li>
<li class="subnav-item">
<a href="#" class="subnav-link">Menuitem 3</a>
</li>
</ul>
</div>
<div class="col-6">
<h3 class="">Some title</h3>
<hr>
<ul class="subnav">
<li class="subnav-item">
<a href="#" class="subnav-link">Menuitem 1</a>
</li>
<li class="subnav-item">
<a href="#" class="subnav-link">Another menuitem</a>
</li>
<li class="subnav-item">
<a href="#" class="subnav-link">Menuitem 3</a>
</li>
</ul>
</div>
</div>
<hr>
<div class="d-flex">
<div class="align-self-center pr-4">
Lorem ipsum dolor sit amet consectetur adipisicing elit. Vitae corrupti reprehenderit provident ipsam quibusdam, iste ad amet exercitationem sunt. Impedit libero aperiam ratione reiciendis dolorem itaque aut quas eos labore.
</div>
<div class="align-self-center">
<a href="#" class="btn btn-outline-primary">Click me</a>
</div>
</div>
</div>
<div class="col-4">
<img src="//placeimg.com/640/480/any" class="img-fluid mb-3" alt="test image">
<p>
Lorem ipsum dolor sit amet consectetur adipisicing elit. Autem, expedita sint quis rem amet, a nihil, non sunt ea quasi.
</p>
<a href="#">See more <i class="fa fa-angle-double-right"></i></a>
</div>
</div>
</div>
</div>
</li>
<li class="nav-item is-parent">
<a class="nav-link" href="#" id="megamenu-dropdown-2" aria-haspopup="true" aria-expanded="false">
Link 2 <i class="fa fa-angle-down"></i>
</a>
<div class="megamenu-content" aria-labelledby="megamenu-dropdown-2">
<div class="container">
<div class="row">
<div class="col-8 pr-5">
<div class="row">
<div class="col-6">
<h3 class="">Some title</h3>
<hr>
<ul class="subnav">
<li class="subnav-item">
<a href="#" class="subnav-link">Menuitem 1</a>
</li>
<li class="subnav-item">
<a href="#" class="subnav-link">Another menuitem</a>
</li>
<li class="subnav-item">
<a href="#" class="subnav-link">Menuitem 3</a>
</li>
<li class="subnav-item">
<a href="#" class="subnav-link">Menuitem 4</a>
</li>
</ul>
</div>
<div class="col-6">
<h3 class="">Another title</h3>
<hr>
<ul class="subnav">
<li class="subnav-item">
<a href="#" class="subnav-link">Menuitem 1</a>
</li>
<li class="subnav-item">
<a href="#" class="subnav-link">Another menuitem</a>
</li>
<li class="subnav-item">
<a href="#" class="subnav-link">Menuitem 3</a>
</li>
<li class="subnav-item">
<a href="#" class="subnav-link">Another menuitem 2</a>
</li>
</ul>
</div>
</div>
<hr>
<div class="d-flex">
<div class="align-self-center pr-4">
Lorem ipsum dolor sit amet consectetur adipisicing elit. Vitae corrupti reprehenderit provident ipsam quibusdam, iste ad amet exercitationem sunt. Impedit libero aperiam ratione reiciendis dolorem itaque aut quas eos labore.
</div>
<div class="align-self-center">
<a href="#" class="btn btn-outline-primary">Click me</a>
</div>
</div>
</div>
<div class="col-4">
<img src="//placeimg.com/641/430/any" class="img-fluid mb-3" alt="test image">
<p>Lorem ipsum dolor sit amet consectetur adipisicing elit. Autem, expedita sint quis rem amet, a nihil, non sunt ea quasi.</p>
<a href="#">Read more <i class="fa fa-angle-double-right"></i></a>
</div>
</div>
</div>
</div>
</li>
<li class="nav-item is-parent">
<a class="nav-link" href="#" id="megamenu-dropdown-3" aria-haspopup="true" aria-expanded="false">
Link 3 <i class="fa fa-angle-down"></i>
</a>
<div class="megamenu-content" aria-labelledby="megamenu-dropdown-3">
<div class="container">
<div class="row">
<div class="col-8 pr-5">
<div class="row">
<div class="col-6">
<h3 class="">Another title</h3>
<hr>
<ul class="subnav">
<li class="subnav-item">
<a href="#" class="subnav-link">Menuitem 1</a>
</li>
<li class="subnav-item">
<a href="#" class="subnav-link">Another menuitem</a>
</li>
<li class="subnav-item">
<a href="#" class="subnav-link">Menuitem 3</a>
</li>
<li class="subnav-item">
<a href="#" class="subnav-link">Menuitem 1</a>
</li>
<li class="subnav-item">
<a href="#" class="subnav-link">Another menuitem</a>
</li>
<li class="subnav-item">
<a href="#" class="subnav-link">Menuitem 3</a>
</li>
</ul>
</div>
<div class="col-6">
<h3 class="">Some title</h3>
<hr>
<ul class="subnav">
<li class="subnav-item">
<a href="#" class="subnav-link">Menuitem 1</a>
</li>
<li class="subnav-item">
<a href="#" class="subnav-link">Another menuitem</a>
</li>
<li class="subnav-item">
<a href="#" class="subnav-link">Menuitem 3</a>
</li>
</ul>
</div>
</div>
<hr>
<div class="d-flex">
<div class="align-self-center pr-4">
Lorem ipsum dolor sit amet consectetur adipisicing elit. Vitae corrupti reprehenderit provident ipsam quibusdam, iste ad amet exercitationem sunt. Impedit libero aperiam ratione reiciendis dolorem itaque aut quas eos labore.
</div>
<div class="align-self-center">
<a href="#" class="btn btn-outline-primary">Click me</a>
</div>
</div>
</div>
<div class="col-4">
<img src="//placeimg.com/640/480/any" class="img-fluid mb-3" alt="test image">
<p>Lorem ipsum dolor sit amet consectetur adipisicing elit. Autem, expedita sint quis rem amet, a nihil, non sunt ea quasi.</p>
<a href="#">Read more <i class="fa fa-angle-double-right"></i></a>
</div>
</div>
</div>
</div>
</li>
<li class="nav-item is-parent">
<a class="nav-link" href="#" id="megamenu-dropdown-4" aria-haspopup="true" aria-expanded="false">
Link 4 <i class="fa fa-angle-down"></i>
</a>
<div class="megamenu-content" aria-labelledby="megamenu-dropdown-4">
<div class="container">
<div class="row">
<div class="col-8 pr-5">
<div class="row">
<div class="col-6">
<h3 class="">Some title</h3>
<hr>
<ul class="subnav">
<li class="subnav-item">
<a href="#" class="subnav-link">Menuitem 1</a>
</li>
<li class="subnav-item">
<a href="#" class="subnav-link">Another menuitem</a>
</li>
<li class="subnav-item">
<a href="#" class="subnav-link">Menuitem 3</a>
</li>
<li class="subnav-item">
<a href="#" class="subnav-link">Menuitem 4</a>
</li>
</ul>
</div>
<div class="col-6">
<h3 class="">Another title</h3>
<hr>
<ul class="subnav">
<li class="subnav-item">
<a href="#" class="subnav-link">Menuitem 1</a>
</li>
<li class="subnav-item">
<a href="#" class="subnav-link">Another menuitem</a>
</li>
<li class="subnav-item">
<a href="#" class="subnav-link">Menuitem 3</a>
</li>
<li class="subnav-item">
<a href="#" class="subnav-link">Another menuitem 2</a>
</li>
</ul>
</div>
</div>
<hr>
<div class="d-flex">
<div class="align-self-center pr-4">
Lorem ipsum dolor sit amet consectetur adipisicing elit. Vitae corrupti reprehenderit provident ipsam quibusdam, iste ad amet exercitationem sunt. Impedit libero aperiam ratione reiciendis dolorem itaque aut quas eos labore.
</div>
<div class="align-self-center">
<a href="#" class="btn btn-outline-primary">Click me</a>
</div>
</div>
</div>
<div class="col-4">
<img src="//placeimg.com/641/430/any" class="img-fluid mb-3" alt="test image">
<p>Lorem ipsum dolor sit amet consectetur adipisicing elit. Autem, expedita sint quis rem amet, a nihil, non sunt ea quasi.</p>
<a href="#">Read more <i class="fa fa-angle-double-right"></i></a>
</div>
</div>
</div>
</div>
</li>
<li class="nav-item">
<a class="nav-link" href="#">
Link without megamenu
</a>
</li>
</ul>
<div class="megamenu-background" id="megamenu-background"></div>
</nav>
<div class="megamenu-dim" id="megamenu-dim"></div>
<section class="hero">
<div class="container pt-4">
<h1 class="display-2 mb-4">Megamenu</h1>
<p class="lead">
Dependencies are: <strong>Bootstrap 4, jQuery, jQuery.hoverIntent, Lodash (debounce and throttle)</strong>
</p>
<p class="lead"><em>Should work quite well™ </em>with mouse hover, clicks/keyboard and touch devices.</p>
<p class="lead">Hover Intent plugin is used to track user mouse movement and not fire the megamenu event if cursor is moved rapidly over the main menu elements.</p>
<p class="lead">Adjusts the menu background height automatically when resizing the browser window. Calculates menu background height from the tallest megamenu content.</p>
<p class="lead">Missing responsive styling :(</p>
</div>
</section>
<section class="bg-light">
<div class="container">
<p>Lorem ipsum dolor, sit amet consectetur adipisicing elit. Nesciunt cumque hic ipsam et. Perferendis voluptatum incidunt maxime eos et officiis exercitationem! Expedita ipsa tenetur porro dolores possimus cum ab sapiente.</p>
</div>
</section>
<section class="bg-white">
<div class="container">
<p>Lorem ipsum dolor, sit amet consectetur adipisicing elit. Nesciunt cumque hic ipsam et. Perferendis voluptatum incidunt maxime eos et officiis exercitationem! Expedita ipsa tenetur porro dolores possimus cum ab sapiente.</p>
</div>
</section>
const $megamenuParentListItem = $('.megamenu-nav > li.is-parent');
const $megamenuBackground = $('#megamenu-background');
const isTouch = 'ontouchstart' in window || !!(navigator.msMaxTouchPoints);
const handleMenuItemOpenState = (elem) => {
elem.addClass('is-open');
elem.find('a').first().attr('aria-expanded', true);
};
const handleMenuItemCloseState = (elem) => {
elem.removeClass('is-open');
elem.find('a').first().attr('aria-expanded', false);
};
const openMegamenu = (bgElem, heightVal) => {
$('body').addClass('megamenu-visible');
bgElem.height(heightVal);
};
const closeMegamenu = (bgElem, heightVal) => {
$('body').removeClass('megamenu-visible');
bgElem.height(heightVal);
};
const $megamenuContentElem = $('.megamenu-nav .megamenu-content');
const getTallestMenuHeight = () => {
let maxHeight = 0;
$megamenuContentElem.each((index, item) => {
if ($(item).outerHeight() > maxHeight) {
maxHeight = $(item).outerHeight();
}
});
return maxHeight;
}
const debouncedClose = _.debounce(closeMegamenu, 400);
const throttledContentHeightCount = _.throttle(getTallestMenuHeight, 100);
let megamenuContentMaxHeight = 0;
window.onresize = () => {
megamenuContentMaxHeight = throttledContentHeightCount();
};
$(() => {
megamenuContentMaxHeight = getTallestMenuHeight();
$megamenuParentListItem.each((index, item) => {
if (!isTouch) {
$(item).hoverIntent({
sensitivity: 10,
interval: 50,
over: () => {
debouncedClose.cancel();
$megamenuParentListItem.removeClass('is-open');
handleMenuItemOpenState($(item));
openMegamenu($megamenuBackground, megamenuContentMaxHeight);
},
out: () => {
handleMenuItemCloseState($(item));
debouncedClose($megamenuBackground, 0);
},
});
}
$(item).find('a').first().on('click touch', () => {
if (!$(item).hasClass('is-open')) {
$megamenuParentListItem.removeClass('is-open');
handleMenuItemOpenState($(item));
openMegamenu($megamenuBackground, megamenuContentMaxHeight);
} else {
handleMenuItemCloseState($(item));
closeMegamenu($megamenuBackground, 0);
}
});
});
$('#megamenu-dim').on('click touch', (e) => {
if ($('body').hasClass('megamenu-visible')) {
e.preventDefault();
$megamenuParentListItem.removeClass('is-open');
closeMegamenu($megamenuBackground, 0);
}
});
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery.hoverintent/1.9.0/jquery.hoverIntent.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.11/lodash.min.js"></script>
$body-bg: #fff;
$nav-bg: #007bff;
$z-index-navbar: 15;
$z-index-megamenu-content: $z-index-navbar - 1;
$z-index-megamenu-bg: $z-index-megamenu-content - 1;
$z-index-megamenu-dim: $z-index-megamenu-bg - 1;
$navbar-height: 54px;
body {
background: $body-bg;
}
section {
padding: 100px 0;
}
.hero {
color: #fff;
background-image: url(//placeimg.com/1500/600/any);
background-repeat: no-repeat;
background-size: cover;
position: relative;
&:before {
content: "";
background: rgba(0,0,0,0.6);
position: absolute;
left: 0;
top: 0;
right: 0;
bottom: 0;
}
.container {
position: relative;
z-index: 2;
}
}
.megamenu {
background: $nav-bg;
z-index: $z-index-navbar;
.megamenu-nav {
padding: 0;
margin: 0;
.nav-item {
display: block;
&.is-open {
> .megamenu-content {
visibility: visible;
opacity: 1;
}
> .nav-link {
background: #fff;
color: #333;
}
}
}
.nav-link {
color: #fff;
padding: 15px 30px;
&:hover {
background: #fff;
color: #333;
}
}
}
.megamenu-content {
position: absolute;
left: 0;
right: 0;
top: $navbar-height;
overflow: hidden;
visibility: hidden;
opacity: 0;
z-index: $z-index-megamenu-content;
transition: all .3s ease-in-out;
.container {
padding: 45px 15px;
}
.subnav {
margin: 0;
padding: 0;
}
.subnav-item {
display: block;
.subnav-link {
padding: 10px 0;
display: block;
}
}
}
}
.megamenu-background {
background: #fff;
position: absolute;
left: 0;
top: $navbar-height;
right: 0;
height: 0;
transition: all .3s ease-in-out;
box-shadow: 0px 10px 20px rgba(0,0,0,0.15);
z-index: $z-index-megamenu-bg;
}
.megamenu-dim {
background: rgba(0,0,0,0.6);
position: fixed;
left: 0;
right: 0;
bottom: 0;
top: $navbar-height;
visibility: hidden;
opacity: 0;
z-index: -$z-index-megamenu-dim;
transition: all .3s ease-in-out;
body.megamenu-visible & {
z-index: $z-index-megamenu-dim;
visibility: visible;
opacity: 1;
}
}
<link href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.1.3/css/bootstrap.min.css" rel="stylesheet" />
<link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css" rel="stylesheet" />
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment