henrywright
henrywright

Reputation: 10250

How to close an open collapsed navbar when clicking outside of the navbar element in Bootstrap 3?

How can I close an open collapsed navbar on clicking outside of the navbar element? Currently, the only way to open or close it is by clicking on the navbar-toggle button.

See here for an example and code:

So far, I have tried the following which doesn't seem to work:

jQuery(document).click(function() {

});

jQuery('.navbar').click(function(event) {
    jQuery(".navbar-collapse").collapse('hide');
    event.stopPropagation();
});

Upvotes: 51

Views: 123012

Answers (18)

Brian
Brian

Reputation: 38035

Here is some code for Bootstrap 5. It is similar to other answers, but includes hiding due to scrolling as well. It should work without modification, though does assume only a single navbar on the page.

<script type="text/javascript">
    document.addEventListener("DOMContentLoaded", function () {
        const navbarToggler = document.querySelector(".navbar-toggler");

        // Get collapse content from data-bs-target on the menu toggle button.
        const navbarCollapse = document.querySelector(
            navbarToggler.dataset.bsTarget
        );

        function hideMenu() {
            if (navbarCollapse.classList.contains("show"))
                navbarToggler.click();
        }

        document.addEventListener("click", function () {
            hideMenu();
        });

        document.addEventListener("scroll", function () {
            hideMenu();
        });
    });
</script>

Upvotes: 1

Kopi Bryant
Kopi Bryant

Reputation: 1364

I know its quite awhile for the answer. But I think the answer here could helps.

Lets say the condition: if user want to close the navbar when click outside but not when user click any element inside of the navbar

use the event.target and target the element's closest classname whether its has the navbar class or not. If yes which means user is clicking element inside of the navbar and not to close the navbar.

$(function() {
    $(document).click(function (event) {
        var clickover = $(event.target);
        var _opened = $(".navbar-collapse").hasClass("navbar-collapse collapse show");
        if (_opened === true && clickover.closest('.navbar').length === 0) {
            $(".navbar-collapse").collapse('hide');
        }
    });
});

Upvotes: 0

Douglas Vicentini
Douglas Vicentini

Reputation: 323

Vanilla Javascript.

Working on Bootstrap 5.2.

window.onload = function () {
    document.addEventListener("click", function (event) {
        // if the clicked element isn't child of the navbar, you must close it if is open
        if (!event.target.closest("#navbar_id") && document.getElementById("navbarSupportedContent").classList.contains("show")) {
            document.getElementById("hamburger_menu_button").click();
        }
    });
}

https://jsfiddle.net/j4tgpbxz/

You just need to add an id to the navbar element, and then check if the clicked element is a child of that same navbar and the content you want to hide (dropdown) is being shown.

Upvotes: 3

gerstavros
gerstavros

Reputation: 49

For latest Bootstrap, this is the correct answer.

$(document).click(function (event) {
    var clickover = $(event.target);
    var $navbar = $(".navbar-collapse");               
    var _opened = $navbar.hasClass("show");
    if (_opened === true && !clickover.hasClass("navbar-toggler")) {      
        $navbar.collapse('hide');
    }
});

It reads if .navbar-collapse has the word show in classes (which means menu is opened) and hides the navbar when you click/tap anywhere.

Upvotes: 2

Andre Duarte
Andre Duarte

Reputation: 61

I had some problems with some answers here, and I would like to also be able to close the expanded menu on demand. So I did it with a simple function, and simulating the click.

function closeMenu(){
  element = document.getElementById('nav_top');
  if(element){
    if(element.classList.contains('show')){
      document.getElementById('navbar_toggler').dispatchEvent(new CustomEvent('click'));
    }
  }
}
$(document).ready(function () {
  $(document).click(function (event) {
    closeMenu();
  });
});

Using this method you can close it when clicked outside, but also you can call the closeMenu() at any time from any other function.

Upvotes: 0

Nasim B. D
Nasim B. D

Reputation: 311

The following code works for me and the advantage is that on small screens, it does not hide the .collapse when you click on its nav parent with .navbar .navbar-expand classes:

$(document).click(function (e) {  
    if($('.collapse').hasClass('show') && !$('nav').is(e.target) && $('nav').has(e.target).length === 0){
        $('.navbar-toggler').click()
    }
})

Upvotes: 1

maxshuty
maxshuty

Reputation: 10730

I had a scenario where I had plain text and I didn't want the panel to close if a user clicks on the plain text on accident. The other answers here will close the panel even if you click on the text of an item that isn't a link.

To fix this I added on to Paul Tarr's answer by wrapping the solution in a check to see whether or not the click occurred anywhere inside:

if ($(event.target).parents(".navbar-collapse").length < 1) { }

The full code would become:

$(document).click(function (event) {
if ($(event.target).parents(".navbar-collapse").length < 1) {
    var clickover = $(event.target);
    var $navbar = $(".navbar-collapse");               
    var _opened = $navbar.hasClass("in");
    if (_opened === true && !clickover.hasClass("navbar-toggle")) {      
        $navbar.collapse('hide');
    }
  }
});

In this demo fiddle you can see that if you click on a non-link inside of the panel it won't collapse it.

Upvotes: 3

Kailyn
Kailyn

Reputation: 473

Converted nozzleman's answer for Bootstrap 4(.3.1):

$(document).ready(function () {
    $(document).click(
        function (event) {
            var target = $(event.target);
            var _mobileMenuOpen = $(".navbar-collapse").hasClass("show");
            if (_mobileMenuOpen === true && !target.hasClass("navbar-toggler")) {
                $("button.navbar-toggler").click();
            }
        }
    );
});

Placed in the ngOnInit().

When the document is loaded, this code waits for click events. If the mobile menu dropdown is open (i.e. the collapsible part of the navbar has the "show" class) and the clicked object (target) is not the mobile menu button (i.e. does not have the "navbar-toggler" class), then we tell the mobile menu button it has been clicked, and the menu closes.

Upvotes: 12

muthu
muthu

Reputation: 1

$(window).click(function (e) {
     if ($(e.target).closest('.codehim-dropdown').length) {
         return;
     }
     if ($(e.target).closest(offCanvas).length) {
         return;
     }

     //check if menu really opened
     if ($(hamburger).hasClass("active")) {
         closeMenu();
     }

     $(dimOverlay).fadeOut();

     $(".menu-items").slideUp();
     $(".dropdown-heading").removeClass("active");

});

Upvotes: 0

Venkanna t
Venkanna t

Reputation: 1

$(document).click(function (event) {
 if ($('.navbar-collapse').attr('aria-expanded') == "true") {
        $('.navbar-collapse:visible').click();
    }
});

Upvotes: 0

Timur
Timur

Reputation: 1

For Bootstrap 4:

$(document).click(function(event) {
  $(event.target).closest(".navbar").length || $(".navbar-collapse.show").length && $(".navbar-collapse.show").collapse("hide")
});

Upvotes: 0

Chloe
Chloe

Reputation: 26294

For Bootstrap 4

Bootstrap 4 doesn't have an in class. This is Coffeescript.

  $(document).click (e)->
    #console.log e.target
    unless $('#toggle-button').has(e.target).length || $('#toggle-menu').has(e.target).length
      $('#toggle-menu').collapse('hide')

So basically, unless you click the button or the menu, close the menu.

Note: Strange, on iOS clicking on text doesn't register a click event, nor a mouseup event. Clicking on an image does fire events though.

Upvotes: 0

Shiva Charan
Shiva Charan

Reputation: 307

Using this works for me.

$(function() {
  $(document).click(function (event) {
    $('.navbar-collapse').collapse('hide');
  });
});

Upvotes: 28

sonxurxo
sonxurxo

Reputation: 5718

I've added a condition to @nozzleman's answer to check if the tap or click has been made on any element within the menu, and if that's the case, not to collapse it.

$(document).ready(function () {
    $(document).click(function (event) {
        var clickover = $(event.target);
        var _opened = $(".navbar-collapse").hasClass("navbar-collapse in");
        if (_opened === true && !clickover.hasClass("navbar-toggle") && clickover.parents('.navbar-collapse').length == 0) {
            $("button.navbar-toggle").click();
        }
    });
});

Upvotes: 1

Paul Tarr
Paul Tarr

Reputation: 530

The accepted answer doesn't appear to work correctly. It only needs to check if "navbar-collapse" has the "in" class. We can then fire the collapse method as expected by using our reference to the navbar.

$(document).click(function (event) {
    var clickover = $(event.target);
    var $navbar = $(".navbar-collapse");               
    var _opened = $navbar.hasClass("in");
    if (_opened === true && !clickover.hasClass("navbar-toggle")) {      
        $navbar.collapse('hide');
    }
});

Upvotes: 47

henrywright
henrywright

Reputation: 10250

The solution I decided to use was taken from the accepted answer here and from this answer

jQuery('body').bind('click', function(e) {
    if(jQuery(e.target).closest('.navbar').length == 0) {
        // click happened outside of .navbar, so hide
        var opened = jQuery('.navbar-collapse').hasClass('collapse in');
        if ( opened === true ) {
            jQuery('.navbar-collapse').collapse('hide');
        }
    }
});

This hides an opened collapsed nav menu if the user clicks anywhere outside of the .navbar element. Of course clicking on .navbar-toggle still works to close the menu too.

Upvotes: 18

nozzleman
nozzleman

Reputation: 9669

Have a look that:

$(document).ready(function () {
    $(document).click(function (event) {
        var clickover = $(event.target);
        var _opened = $(".navbar-collapse").hasClass("navbar-collapse in");
        if (_opened === true && !clickover.hasClass("navbar-toggle")) {
            $("button.navbar-toggle").click();
        }
    });
});

Your fiddle works with that: http://jsfiddle.net/52VtD/5718/

Its a modified version of this answer, which lacks the animation and is also a tiny bit more complicated.

I know, invoking the click() isn't very elegant, but collapse('hide') did not work for me either, and i think the animation is a bit nicer than adding and removing the classes hardly.

Upvotes: 54

pstenstrm
pstenstrm

Reputation: 6489

stopPropagation() is not always the best solution. Rather use something like:

jQuery(document.body).on('click', function(ev){
    if(jQuery(ev.target).closest('.navbar-collapse').length) return; // Not return false

    // Hide navbar
});

I think it's dangerous to assume that you never want to listen to any other event from the .navbar. Which is impossible if you use stopPropagation().

Upvotes: 4

Related Questions