Bootstrap 4 Collapsing Navbar
Progressively collapse menu items into a dropdown menu
Bootstrap 4 has a nice responsive Navbar with 5 different breakpoint options. However, when there are many menu items, none of the responsive breakpoints are ideal, and the Navbar items start to wrap which doesn’t look good.
Here is an alternative responsive Navbar that automatically collapses (as the viewport is resized) the extra overflowing menu items into a Dropdown menu.
This implementation is with jQuery, but this JavaScript logic could just as easily be implemented as a Vue, React or Angular component.
Here’s the basic logic:
- If the Navbar height is larger than it’s container, the menu items have wrapped and therefore we ADD items to the dropdown
- Otherwise, we REMOVE items from the dropdown and return them to the Navbar
- We check the above logic when the DOM is loaded, and while the window is resized.
The jQuery Function
var autocollapse = function (menu,maxHeight) {
var nav = $(menu);
var navHeight = nav.innerHeight();if (navHeight >= maxHeight) { $(menu + ' .dropdown').removeClass('d-none');
$(".navbar-nav").removeClass('w-auto').addClass("w-100");
while (navHeight > maxHeight) {
// add child to dropdown
var children = nav.children(menu + ' li:not(:last-child)');
var count = children.length;
$(children[count - 1]).prependTo(menu + ' .dropdown-menu');
navHeight = nav.innerHeight(); }
$(".navbar-nav").addClass("w-auto").removeClass('w-100');} else {
var collapsed = $(menu+'.dropdown-menu').children(menu+'li');
if (collapsed.length===0) {
$(menu + ' .dropdown').addClass('d-none');
}
while (navHeight < maxHeight &&
(nav.children(menu + ' li').length > 0) &&
collapsed.length > 0) { // remove child from dropdown
collapsed = $(menu + ' .dropdown-menu').children('li');
$(collapsed[0]).insertBefore(nav.children(menu+'li:last-child'));
navHeight = nav.innerHeight(); } if (navHeight > maxHeight) {
autocollapse(menu,maxHeight);
}} // end if-else}; // end function$(document).ready(function () { // when the page loads
autocollapse('#nav',50);
// when the window is resized
$(window).on('resize', function () {
autocollapse('#nav',50);
});});
The HTML Markup
And the Navbar markup is the standard Bootstrap 4 responsive Navbar with all of the Navbar Items and a Dropdown on the right.
<nav class="navbar navbar-expand navbar-dark bg-info">
<a class="navbar-brand pb-2" href="#">Bootstrap 4</a>
<button class="navbar-toggler" type="button" data- toggle="collapse" data-target="#navbarNavDropdown" aria-controls="navbarNavDropdown">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarNavDropdown">
<ul class="navbar-nav">
<li class="nav-item">
<a class="nav-link" href="#">Home</a>
</li>
</ul>
<ul class="navbar-nav ml-auto" id="nav">
<li class="nav-item">
<a class="nav-link" href="#">Features</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#">Pricing</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#">Item 4</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#">Item 5</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#">Item 6</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#">Item 7</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#">Item 8</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#">Item 9</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#">Item 10</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#">Item 11</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#">Item 12</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#">Item 13</a>
</li>
<li class="nav-item dropdown d-none">
<a class="nav-link dropdown-toggle" href="#" id="navbarDropdownMenu" role="button" data-toggle="dropdown">
Menu
</a>
<ul class="dropdown-menu dropdown-menu-right">
</ul>
</li>
</ul>
</div>
</nav>
Putting it all together, here is the complete Navbar:
Grab the source code at Codeply.
Thanks for reading, and check out the other helpful Bootstrap development resources at Bootstrap4.guide
-T