DEV Community

Cover image for Bootstrap 4 Self-collapsing Navbar
Tom Michew for Codeply

Posted on

Bootstrap 4 Self-collapsing Navbar

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 very good ๐Ÿ˜.

Here is an alternative responsive Navbar that auto-magically ๐Ÿ˜Ž 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.


jQuery Logic (could use plain JS instead)

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);
        }

    }
}

$(document).ready(function () {

    // when the page loads
    autocollapse('#nav',50); 

    // when the window is resized
    $(window).on('resize', function () {
        autocollapse('#nav',50); 
    });

})


HTML Markup

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">
    <div class="container-fluid">
    <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" aria-expanded="false" aria-label="Toggle navigation">
        <span class="navbar-toggler-icon"></span>
    </button>
    <div class="collapse navbar-collapse justify-content-end" id="navbarNavDropdown">
        <ul class="navbar-nav align-self-end" 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 13</a>
            </li>
            <li class="nav-item dropdown d-none">
                <a class="nav-link" href="#" id="navbarDropdownMenu" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
                  <span class="navbar-toggler-icon"></span>
                </a>
                <ul class="dropdown-menu dropdown-menu-right bg-info" aria-labelledby="navbarDropdownMenu">
                </ul>
            </li>
        </ul>
    </div>
    </div>
</nav>

Thanks for reading!

Demo | Source

Top comments (0)