42

I'm using a Bootstrap responsive navbar. When the navbar is collapsed and I open the menu and click on a menu item, the menu doesn't close automatically, and I have to do it myself manually.

Is it possible to make the menu close automatically after clicking on one of the buttons?

nc4pk
  • 143
  • 2
  • 9
  • 1
    Be aware that all the below answers since this comment date will also prevent you to click a dropdown within the menu itself. – HenryW Mar 03 '14 at 18:32
  • But the Aug-Sep answers with `a:not(.dropdown-toggle)` do allow you to click a dropdown. But also be aware that almost all these answers give a FOUC when viewed on a desktop, or do a visible menu redraw. A quick hack to fix this is to select on window size: `if($(window).width() < 480) $(".navbar-collapse").collapse('hide');` – EML Feb 09 '15 at 14:26
  • I wish this was provided as default behavior by twitter bootstrap – kittu Dec 06 '16 at 17:24
  • @kittu Indeed! It should be default behaviour. Luckily I use no JavaScript and use `data-bs-toggle`, see my solution: https://stackoverflow.com/a/75808063/10686802 – Remzi Cavdar Mar 22 '23 at 03:23

14 Answers14

46

Working solution for bootstrap 3

$('.navbar-collapse a').click(function(){
    $(".navbar-collapse").collapse('hide');
});
Maximus
  • 2,906
  • 4
  • 35
  • 55
41

Edit: As Maximus points out below, the 3.x bootstrap solution is:

$('.navbar-collapse a').click(function(){
    $(".navbar-collapse").collapse('hide');
});

https://jsfiddle.net/yohuLuj2/


Old Answer for 2.x bootstrap:

You should be able to do that by adding a click handler to the list items and then closing the nav that way.

$('.nav-collapse').click('li', function() {
    $('.nav-collapse').collapse('hide');
});

Heres a jsfiddle: http://jsfiddle.net/hajpoj/By6ym/4/

Community
  • 1
  • 1
hajpoj
  • 13,299
  • 2
  • 46
  • 63
34

I just replicate the two attributes of the btn-navbar (data-toggle="collapse" data-target=".nav-collapse") on each link like this:

<div class="nav-collapse">
  <ul class="nav" >
    <li class="active"><a href="#home" data-toggle="collapse" data-target=".nav-collapse">Home</a></li>
    <li><a href="#about" data-toggle="collapse" data-target=".nav-collapse">About</a></li>
    <li><a href="#portfolio" data-toggle="collapse" data-target=".nav-collapse">Portfolio</a></li>
    <li><a href="#services" data-toggle="collapse" data-target=".nav-collapse">Services</a></li>
    <li><a href="#contact" data-toggle="collapse" data-target=".nav-collapse">Contact</a></li>
  </ul>
</div>
bathyscapher
  • 1,615
  • 1
  • 13
  • 18
Zu1779
  • 2,178
  • 1
  • 18
  • 17
  • 1
    A non-jquery solution works much better and is more maintainable! – Doguhan Uluca Sep 05 '14 at 02:55
  • 2
    Best answer here if you're using a framework such as Angular and don't want to clutter up the controller. – SWalters Mar 12 '15 at 16:54
  • 3
    If you ever use this on a non-collapsed menu, you still get the collapse affect, which looks very weird. – Richard Apr 22 '15 at 15:05
  • 1
    @Stony You have to add `.in` to the end of the `data-target` value: `data-target=".navbar-collapse.in"`. From comment in this answer: http://stackoverflow.com/a/21797534/89818 – caw Jun 07 '16 at 16:10
11

Only thing I'd add to jason's solution is the exception for dropdowns. You don't want to close your menu if someone is simply clicking to toggle the submenu. So…

$('.navbar-collapse a:not(.dropdown-toggle)').click(function(){
    $(".navbar-collapse").collapse('hide');
});
Mike Eberly
  • 111
  • 1
  • 3
8

@Mike's dropdown solution worked for me except that the items within the dropdown toggle wouldn't hide the menu so I made sure to add this:

$('.navbar-collapse .dropdown-menu').click(function(){
    $(".navbar-collapse").collapse('hide');
});
Sarah Wever
  • 81
  • 1
  • 2
3

Just remember to traverse up the DOM tree and close the associated Navbar, and not all Navbars. In particular for Bootstrap 3, use something similar to the following code snippet:

$("body").on("click", ".navbar-collapse a", function() {
  var $this = $(this);

  setTimeout(function() {
     $this.closest(".navbar-collapse").collapse('hide');
  }, 350);
});
KyleMit
  • 30,350
  • 66
  • 462
  • 664
Behrang
  • 46,888
  • 25
  • 118
  • 160
3

Another problem is when you see the navbar on desktop, it try to hide/show the navbar, so I made this:

$('.navbar-collapse a:not(.dropdown-toggle)').click(function(){
    if($(window).width() < 768 )
        $('.navbar-collapse').collapse('hide');
});
Sergio
  • 609
  • 1
  • 7
  • 11
  • 1
    I don't understand your comment, but your addition(`$(window.width()`) prevents a nasty FOUC when viewed on a desktop site, so +1. – EML Feb 09 '15 at 14:22
2

I complete the answers by adding button click management:

$(document).on('click', '.navbar-collapse.collapse.in a:not(.dropdown-toggle)', function() {
    $(this).closest(".navbar-collapse").collapse('hide');
});
$(document).on('click', '.navbar-collapse.collapse.in button:not(.navbar-toggle)', function() {
    $(this).closest(".navbar-collapse").collapse('hide');
});
Camel
  • 345
  • 2
  • 7
0

My problem was, I was creating single page layout with anchors. So, when you downsize the window, menu hide on link click perfectly. Thanks to above user who gave me clue. But, when upsize window, the bind event always there (without reloading, though). So, here what I did. Hope it helps someone :)

jQuery.noConflict();
(function($){
    $('ul#menu-menu-with-anchors li a, a[href="#top"]').click(function(){
        $('html, body').animate({
            scrollTop: $( $.attr(this, 'href') ).offset().top - ($('body').hasClass('admin-bar') ? 160 : 130)
        }, 500);
        return false;
    });

    bindUnbindNavToggle($);
    $(window).resize(function(){
        bindUnbindNavToggle($);
    });

})(jQuery);

function bindUnbindNavToggle($){
    if( $('button.navbar-toggle').css('display') != 'none' ) {
        $('.navbar-collapse ul li a').on('click', function(){
           $('.navbar-collapse').collapse('hide');
            return false;
        });
    }
    else {
        $('.navbar-collapse ul li a').on('click', function(){
            return false;
        });
    }
}
Haroon
  • 155
  • 2
  • 10
0

If you use Angular, you can bind the collapsing to the route navigation:

$scope.$on('$routeChangeSuccess', function(event, toState, toParams, fromState, fromParams){ $(".navbar-collapse").collapse('hide'); });
miz
  • 1
0

Simply put this code in main.js

 $(document).on('click', '.navbar-collapse.in', function (e) {
    if ($(e.target).is('a')) {
        $(this).collapse('hide');
    }
});
Joee
  • 1,834
  • 18
  • 19
0

Maybe someone need to hide menu when just click to somewhere else (i have supposed like there is no submenus). Then just add this code somewhere after jquery, bootstrap.js

$('button.navbar-toggle').focusout(function(){
        $(".navbar-collapse").collapse('hide');
    });
0

ZU1779 answer is my favourite.

Anyway with component-based implementations (like Bootstrap-vue) will not work.

In this case you could add an event listener on links that call a function that emulates the click on collapse button, link this:

collapseNav = function() {
  document
    .getElementsByClassName('navbar-toggler')[0]
    .dispatchEvent(new Event('click'))
}

Hope could be useful.

bubbakk
  • 139
  • 2
  • 6
0

Bootstrap 5.3 - update 2023

All the answers here are either very outdated doing things with jQuery or don't work anymore.

The following works with Bootstrap 5.2 and up:

<div class="collapse navbar-collapse" id="main-menu-navbar">
    <ul class="navbar-nav me-auto my-2 my-lg-0">
        <li class="nav-item">
            <a class="nav-link d-lg-none" href="/">
            <span data-bs-toggle="collapse" data-bs-target="#main-menu-navbar">Home</span>
            </a>
            <a class="nav-link d-none d-lg-block" href="/">Home</a>
        </li>
    </ul>
</div>

MRE of a navbar

See example below of a navbar with 2 menu items:

<nav class="navbar navbar-expand-lg bg-body-tertiary">
    <div class="container">
        <a class="navbar-brand" href="/">
            <!-- Replace SVG below for your own logo -->
            <svg width="40" height="40">
                <image xlink:href="https://svgsilh.com/svg_v2/1801287.svg" width="40" height="40"/>
            </svg>
        </a>
        <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#main-menu-navbar"
            aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
        <span class="navbar-toggler-icon"></span>
        </button>
        <div class="collapse navbar-collapse" id="main-menu-navbar">
            <ul class="navbar-nav me-auto my-2 my-lg-0">
                <li class="nav-item">
                    <a class="nav-link d-lg-none" href="/">
                    <span data-bs-toggle="collapse" data-bs-target="#main-menu-navbar">Home</span>
                    </a>
                    <a class="nav-link d-none d-lg-block" href="/">Home</a>
                </li>
            </ul>
        </div>
    </div>
</nav>

Why 2 links in a nav-item?

Because if you use data-bs-toggle="collapse" data-bs-target="#main-menu-navbar" your menu will "flash/reload" on desktop too, so the first link will hide on lg and wider screens and the second link will do the opposite, hide on screens smaller than lg

Remzi Cavdar
  • 135
  • 1
  • 13