Bootstrap 4 Self-collapsing Navbar
Tags: showdev, bootstrap, webdev, html
Published: 2020-04-06 17:54:01

Bootstrap 4 has a [nice responsive Navbar](http://getbootstrap.com/docs/4.1/components/navbar/#responsive-behaviors) 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](https://www.codeply.com/v/4lou9vnMnc) | [Source](https://www.codeply.com/go/IETSah3bFG)