133
votes

This is not a submenu dropdown, the category is class li as in the picture:

enter image description here

By selecting a category from the responsive menu (the template is just one page), I want to hide nav collapse automatically when clicking. Also stroll to use as navigation, since the template has only one page. I seek a solution that does not affect it, here is the HTML code of menu:

    <!-- NAVBAR
  ================================================== -->
<div class="navbar navbar-fixed-top">
  <div class="navbar-inner">
    <div class="container">
      <a class="btn btn-navbar" data-toggle="collapse" data-target=".nav-collapse">
      <span class="icon-bar"></span>
      <span class="icon-bar"></span>
      <span class="icon-bar"></span>
      </a>
      <a class="brand" href="#">Carousel Demo</a>
      <div class="nav-collapse">
        <ul class="nav" >
          <li class="active"><a href="#home">Home</a></li>
          <li><a href="#about">About</a></li>
          <li><a href="#portfolio">Portfolio</a></li>
          <li><a href="#services">Services</a></li>
          <li><a href="#contact">Contact</a></li>
          <!-- dropdown -->
        </ul>
        <!-- /.nav -->
      </div>
      <!--/.nav-collapse -->
    </div>
    <!-- /.container -->
  </div>
  <!-- /.navbar-inner -->
</div>
<!-- /.navbar -->
30
and my solution working or not? - WooCaSh
@WooCaSh Worked rather the order of their solution custom.js was wrong, I noticed $ ('nav a'). On ('click', function () {and in my case it is a class, then $ ('. nav a '). on (' click ', function () {. thank you, you helped me a lot! - Tim Vitor
If you don't want to try and compare all these solutions here yourself, edit #1 from this answer is what you should do. - caw
You could see my answer here stackoverflow.com/questions/14248194/… - Camel

30 Answers

166
votes

try this:

$('.nav a').on('click', function(){
    $('.btn-navbar').click(); //bootstrap 2.x
    $('.navbar-toggle').click(); //bootstrap 3.x by Richard
    $('.navbar-toggler').click(); //bootstrap 4.x
});
134
votes

I just replicate the 2 attributes of the btn-navbar (data-toggle="collapse" data-target=".nav-collapse.in") 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.in">Home</a></li>
    <li><a href="#about" data-toggle="collapse" data-target=".nav-collapse.in">About</a></li>
    <li><a href="#portfolio" data-toggle="collapse" data-target=".nav-collapse.in">Portfolio</a></li>
    <li><a href="#services" data-toggle="collapse" data-target=".nav-collapse.in">Services</a></li>
    <li><a href="#contact" data-toggle="collapse" data-target=".nav-collapse.in">Contact</a></li>
  </ul>
</div>

In the Bootstrap 4 Navbar, in has changed to show so the syntax would be:

data-toggle="collapse" data-target=".navbar-collapse.show"

60
votes
$(function() {
    $('.nav a').on('click', function(){ 
        if($('.navbar-toggle').css('display') !='none'){
            $('.navbar-toggle').trigger( "click" );
        }
    });
});
45
votes

Better to use default collapse.js methods (V3 docs, V4 docs):

$('.nav a').click(function(){
    $('.nav-collapse').collapse('hide');
});
31
votes

Even more elegant without a lick of duplicated code, is to simply apply the data-toggle="collapse" and data-target=".nav-collapse" attributes to the nav itself:

<nav class="nav-collapse" data-toggle="collapse" data-target=".nav-collapse">
  <ul class="nav">
    <li class="active"><a href="#home">Home</a></li>
    <li><a href="#about">About</a></li>
    <li><a href="#portfolio">Portfolio</a></li>
    <li><a href="#services">Services</a></li>
    <li><a href="#contact">Contact</a></li>
  </ul>
</nav>

Super clean, no JavaScript required. Works great, so long as your your nav a elements have plenty enough padding for fat fingers, and you aren't preventing click event bubbling via e.stopPropagation() when users click on nav a items.

17
votes

Update your

<li>
  <a href="#about">About</a>
</li>

to

<li>
  <a data-toggle="collapse" data-target=".nav-collapse" href="#about">About</a>
</li>

This simple change worked for me.

Ref: https://github.com/twbs/bootstrap/issues/9013

13
votes

The navigation should be closed any time a user clicks anywhere on the body - not just navigation elements. Say menu is open, but user clicks in the page body. User expects to see menu close.

You also have to make sure toggle button is visible, otherwise a jump is seen in menu.

$(document).ready(function() { 

$("body").click(function(event) {
        // only do this if navigation is visible, otherwise you see jump in navigation while collapse() is called 
         if ($(".navbar-collapse").is(":visible") && $(".navbar-toggle").is(":visible") ) {
            $('.navbar-collapse').collapse('toggle');
        }
  });

});
13
votes

Tested on Bootstrap 3.3.6 - work's!

$('.nav a').click(function () {
    $('.navbar-collapse').collapse('hide');
});
7
votes

Try this > Bootstrap 3

Brilliant exacly what I was looking for, however I had some clashes with the javascript and the bootstrap modal, this fixed it.

    $(function() {
    $('.navbar-nav').on('click', function(){ 
        if($('.navbar-header .navbar-toggle').css('display') !='none'){
            $(".navbar-header .navbar-toggle").trigger( "click" );
        }
    });
});

Hope this helps.

6
votes

This worked well for me. Its the same as the accepted answer but fixes the issue related to the desktop/tablet view

$('.navbar-nav a').on('click', function () {
        if (window.innerWidth <= 768) {
            $(".navbar-toggle").click();
        }
    });
6
votes

$('.nav a').click(function () {
    $('.navbar-collapse').collapse('hide');
});
4
votes

I think it's better to use default Bootstrap 3's collapse.js methods using the .navbar-collapse as the collapsible element you wish to hide as shown below.

Other solutions may cause other undesired problems with the way elements display or function in your web page. Therefore, while some solutions may appear to fix your initial problem it may very well introduce others, so make sure you run thorough testing of your site after any fix.

To see this code in action:

  1. Press "Run This Code Snippet" below.
  2. Press "Full Page" button.
  3. Scale window until drop-down activates.
  4. Then select a menu option and voila!

Cheers!

$('.nav a').click(function() {
  $('.navbar-collapse').collapse('hide');  
});
<html lang="en">
  <head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="author" content="Franciscus Agnew">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <!-- The above 3 meta tags *must* come first in the head; any other head content must come *after* these tags -->
    <title>Bootstrap Navbar Collapse Function</title>

    <!-- Latest compiled and minified CSS -->
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css" integrity="sha384-1q8mTJOASx8j1Au+a5WDVnPi2lkFfwwEAa8hDDdjZlpLegxhjVME1fgjWPGmkzs7" crossorigin="anonymous">

    <!-- HTML5 shim and Respond.js for IE8 support of HTML5 elements and media queries -->
    <!-- WARNING: Respond.js doesn't work if you view the page via file:// -->
    <!--[if lt IE 9]>
      <script src="https://oss.maxcdn.com/html5shiv/3.7.2/html5shiv.min.js"></script>
      <script src="https://oss.maxcdn.com/respond/1.4.2/respond.min.js"></script>
    <![endif]-->
  </head>
  
  <body>
    <header>
      <nav class="navbar navbar-default navbar-fixed-top" role="navigation">
        <div class="container">
          <div class="navbar-header">
            <button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar" aria-expanded="false" aria-expanded="navbar"><span class="sr-only">Toggle navigation</span>Menu <span class="glyphicon glyphicon-chevron-down"></span></button>
            <a class="navbar-brand" href="#">Brand Logo</a>
          </div><!-- navbar-header -->
    
          <div class="collapse navbar-collapse" id="navbar">
            <ul class="nav navbar-nav navbar-right">
              <li class="active"><a href="#">Home</a></li>
              <li><a href="#about">About</a></li>
              <li><a href="#portfolio">Portfolio</a></li>
              <li><a href="#services">Services</a></li>
              <li><a href="#staff">Staff</a></li>
              <li><a href="#contact">Contact</a></li>
            </ul><!-- navbar-right -->
          </div><!-- navbar-collapse -->
          
        </div><!-- container -->
      </nav><!-- navbar-fixed-top -->
    </header>
    
    <!-- jQuery (necessary for Bootstrap's JavaScript plugins) -->
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
    
    
    <!-- Include all compiled plugins (below), or include individual files as needed -->
    <!-- Latest compiled and minified JavaScript -->
    <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/js/bootstrap.min.js" integrity="sha384-0mSbJDEHialfmuBBQP6A4Qrprq5OVfW37PRR3j5ELqxss1yVqOtnepnHVP9aJ7xS" crossorigin="anonymous"></script>
    
    <!-- Custom Navbar Collapse Script Solution -->
    <script>
      $('.nav a').click(function() {
        $('.navbar-collapse').collapse('hide');  
      });
    </script>
  </body>
</html>
3
votes

On each dropdown link put data-toggle="collapse" and data-target=".nav-collapse" where nav-collapse is the name you give it to the dropdown list.

<ul class="nav" >
      <li class="active"><a href="#home">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>
      <!-- dropdown -->
  </ul>

This is working perfectly on screen that have a dropdown like mobile screens, but on desktop and tablet it creates a flickr. This is because the .collapsing class is applied. To remove the flickr I created a media query and inserted overflow hidden to the collapsing class.

@media (min-width: 768px) {
.collapsing {
    overflow: inherit;
  }
}
3
votes

Adding the data-toggle="collapse" data-target=".navbar-collapse.in" to the tag <a> worked for me.

<div>

        <button type="button" class="navbar-toggle"  data-toggle="collapse" data-target=".navbar-collapse">
          <span class="icon-bar"></span>
          <span class="icon-bar"></span>
          <span class="icon-bar"></span>
        </button>
    </div>
            <div class="navbar-collapse collapse">
            <ul class="nav navbar-nav navbar-right">
                <li class="nav-item"><a
                    href="#" data-toggle="collapse" data-target=".navbar-collapse.in" class="nav-link" >Home
                </a></li>
            </ul>
    </div>
2
votes

Here's how I did it. If there is a smoother way, please please tell me.

Inside the <a> tags where the links for the menu are I added this code:

onclick="$('.navbar-toggle').click()"

It preserves the slide animation. So in full use it would look like this:

<nav class="navbar navbar-inverse navbar-fixed-top" role="navigation" ng-controller="topNavController as topNav">
<div class="container">
    <div class="navbar-header">
        <button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar" aria-expanded="false" aria-controls="navbar">
            <span class="sr-only">Toggle navigation</span>
            <span class="icon-bar"></span>
            <span class="icon-bar"></span>
            <span class="icon-bar"></span>
        </button>
        <a class="navbar-brand" href="home.html">My Cool Site</a>
    </div>
    <div id="navbar" class="navbar-collapse collapse">
        <ul class="nav navbar-nav">
            <li class="active" onclick="$('.navbar-toggle').click()"><a href="home.html" onclick="$('.navbar-toggle').click()"><i class="fa fa-home"></i> Home</a></li>
            <li><a href="aboutus.html" onclick="$('.navbar-toggle').click()">About Us</a></li>
        </ul>
    </div><!--/.nav-collapse -->
</div>

1
votes
$(function() {
    $('.nav a').on('click touchstart', function(){ 
        if($('.navbar-toggle').css('display') !='none'){
            $(".navbar-toggle").trigger( "click" );
        }
    });
});

// NOTE I added the "touchstart" for mobile touch. touchstart/end has no delay

1
votes

This is the best solution I have used.

$(document).ready(function () {

        $('.nav a').on('click', function () {

            if ($(".btn-navbar").is(":visible") ){ $(".btn-navbar").trigger("click"); } //bootstrap 2.x
            if ($(".navbar-toggle").is(":visible")) { $(".navbar-toggle").trigger("click"); } //bootstrap 3.x
        });

    });
1
votes

For those who have noticed desktop navbars flicker when using this solution:

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

A simple solution to that problem is to reference the collapsed navbar only by checking for the presence of 'in':

$('.navbar-collapse .nav a').on('click', function(){
    if($('.navbar-collapse').hasClass('in'))
    {
        $(".navbar-collapse").collapse('hide');
    }
});

This collapses the navbar on click when the navbar is in mobile mode, but will leave alone the desktop version. This avoids the flickering many people have witnessed occurring on desktop versions.

Additionally, if you have a navbar with dropdown menus you won't be able to see these as the navbar will be hidden as soon as you click on them, so if you have dropdown menus (like I do!), use the following:

$('.nav a').on('click', function(e){
    if(!$(this).closest('li').hasClass('dropdown') & $( '.navbar-collapse').hasClass('in'))
    {
        $(".navbar-collapse").collapse('hide');
    }
});

This looks for the presence of the dropdown class above the link clicked on in the DOM, if it exists, then the link was intending to launch a drop down menu and consequently the menu isn't hidden. When you click on a link within the dropdown menu, the navbar will hide correctly.

1
votes
$("body,.nav a").click(function (event) {

    // only do this if navigation is visible, otherwise you see jump in
    //navigation while collapse() iS called 
    if ($(".navbar-collapse").is(":visible") && $(".navbar-toggle").is(":visible")) {
    $('.navbar-collapse').collapse('toggle');
  }
});
1
votes

100% working:-

Add in HTML

<div id="myMenu" class="nav-collapse">

Javascript

 $(function(){ 
 var navMain = $("#myMenu");
 navMain.on("click", "a", null, function () {
     navMain.collapse('hide');
 });
});
0
votes

This hides nav collapse instead of animating it but same concept as above answer

JS:

$('.nav a').on('click', function () {
    $("#funk").toggleClass('in collapse');
});

HTML:

<div class="navbar-collapse" id="funk">

I prefer this on single page sites because I use localScroll.js that already animates.

0
votes

Mobile view: how to hide toggle navigation in bootstrap + dropdown + jquery + scrollto with navigation items that points to anchors/ids on the same page, one page template

The issue I was experimenting with any of the above solutions was that they are collapsing only the submenu items, while the navigation menu doesn't collapse.

So I did my thought.. and what can we observe? Well, every time we/the users click an scrollto link, we want the page to scroll to that position and contemporaneously, collapse the menu to restore the page view.

Well... why not to assign this job to the scrollto functions? Easy :-)

So in the two codes

// scroll to top action
$('.scroll-top').on('click', function(event) {
    event.preventDefault();
    $('html, body').animate({scrollTop:0}, 'slow');

and

// scroll function
function scrollToID(id, speed){
var offSet = 67;
var targetOffset = $(id).offset().top - offSet;
var mainNav = $('#main-nav');
    $('html,body').animate({scrollTop:targetOffset}, speed);
if (mainNav.hasClass("open")) {
    mainNav.css("height", "1px").removeClass("in").addClass("collapse");
    mainNav.removeClass("open");
}

I've just added the same command in both the functions

    if($('.navbar-toggle').css('display') !='none'){
    $(".navbar-toggle").trigger( "click" );
}

(kudos to one of the above contributors)

like this (the same should be added to both the scrolls)

$('.scroll-top').on('click', function(event) {
    event.preventDefault();
    $('html, body').animate({scrollTop:0}, 'slow');
if($('.navbar-toggle').css('display') !='none'){
    $(".navbar-toggle").trigger( "click" );
}
});

if you wanna see it in action just check it out recupero dati da NAS

0
votes

Bootstrap3 users try the given below code. It worked for me.

function close_toggle() {
   if ($(window).width() <= 768) {
      $('.nav a').on('click', function(){
          $(".navbar-toggle").click();
      });
   }
   else {
     $('.nav a').off('click');
   }
}
close_toggle();

$(window).resize(close_toggle);
0
votes

Bootstrap sets a .in class on the Collapse element to trigger the animation – to open it. If you simply remove the .in class, the animation doesn't run, but will hide the element – not exactly what you want.

Likely faster to run an if statement to check if the default bootstrap class .in has been set on the element.

So this code just says:

if my element has the class .in applied, close it by triggering the default Bootstrap animation. Otherwise run the default Bootstrap action/animation of opening it

$('#navbar a').on('click touchstart', function() {
    // if .in class is set on element, the element is visible – you want to hide it
    if ($('#navbar').hasClass('in')) {
        // collapse toggle will remove the .in class and animate the element closed 
        $('#navbar').collapse('toggle');
    }
})
0
votes

Add an id then to each

<li> add data-target="myMenu" data-toggle="collapse"
<div id="myMenu" class="nav-collapse">
    <ul class="nav">
      <li class="active" data-target="myMenu" data-toggle="collapse"><a href="#home">Home</a></li>
      <li data-target="myMenu" data-toggle="collapse"><a href="#about">About</a></li>
      <li data-target="myMenu" data-toggle="collapse"><a href="#portfolio">Portfolio</a></li>
      <li data-target="myMenu" data-toggle="collapse"><a href="#services">Services</a></li>
      <li data-target="myMenu" data-toggle="collapse"><a href="#contact">Contact</a></li>
    </ul>
</div>
0
votes

Another quick solution for Bootstrap 3.* could be:

$( document ).ready(function() {
    //
    // Hide collapsed menu on click
    //
    $('.nav a').each(function (idx, obj) {
        var selected = $(obj);

        selected.on('click', function() {
            if (selected.closest('.collapse.in').length > 0) {
                $('.navbar-toggle').click(); //bootstrap 3.x by Richard
            }
        });
    });
});
0
votes

I posted a solution that works with Aurelia here: https://stackoverflow.com/a/41465905/6466378

The problem is you can not just add data-toggle="collapse" and data-target="#navbar" to your a elements. And jQuery does not work wenn in an Aurelia or Angular environment.

The best solution for me was to create a custom attribute that listens to the corresponding media query and adds in the data-toggle="collapse"attribute if desired:

<a href="#" ... collapse-toggle-if-less768 data-target="#navbar"> ...

The custom attribute with Aurelia looks like this:

import {autoinject} from 'aurelia-framework';

@autoinject
export class CollapseToggleIfLess768CustomAttribute {
  element: Element;

  constructor(element: Element) {
    this.element = element;
    var mql = window.matchMedia("(min-width: 768px)");
    mql.addListener((mediaQueryList: MediaQueryList) => this.handleMediaChange(mediaQueryList));
    this.handleMediaChange(mql);
  }

  handleMediaChange(mediaQueryList: MediaQueryList) {
    if (mediaQueryList.matches) {
      var dataToggle = this.element.attributes.getNamedItem("data-toggle");
      if (dataToggle) {
        this.element.attributes.removeNamedItem("data-toggle");
      }
    } else {
      var dataToggle = this.element.attributes.getNamedItem("data-toggle");
      if (!dataToggle) {
        var dataToggle = document.createAttribute("data-toggle");
        dataToggle.value = "collapse";
        this.element.attributes.setNamedItem(dataToggle);
      }
    }
  }
}
0
votes

I'm on Bootstrap 4, using fullPage.js with a fixed top nav, and tried everything listed here, with mixed results.

  • Tried the best, clean way :

    data-toggle="collapse" data-target=".navbar-collapse.show"
    

    The menu would collapse, but the href links wouldn't lead anywhere.

  • Tried the logical other ways :

    $('myClickableElements').on('click touchstart', function(){
      $(".navbar-collapse.show").collapse('hide');
      // or
      $(".navbar-collapse.show").collapse('toggle');
      // or
      $('.navbar-toggler').click()
    });
    

    There would be some weird behavior because of the touchstart event : the clicked buttons would end up not be the ones I actually clicked, hence breaking the links. Plus it would add the .show class to some other unrelated dropdowns in my nav, causing some more weird stuff.

  • Tried to change div to li
  • Tried to e.preventDefault() and e.stopPropagation()
  • Tried and tried more

Nothing would work.

So, instead, I had the (so far) marvelous idea of doing that :

$(window).on('hashchange',function(){
   $(".navbar-collapse.show").collapse('hide');
});

I already had stuff in that hashchange function, si I just had to add this line.

It actually does exactly what I want : collapsing the menu when the hash changes (i.e. a click leading somewhere else has occurred). Which is good, cause I can now have links in my menu that won't collapse it.

Who knows, maybe this will help someone in my situation!

And thanks to everyone who has participated in that thread, lots of info to be learned here.

0
votes

In most cases you will only want to call the toggle function if the toggle button is visible...

if ($('.navbar-toggler').is(":visible")) $('.navbar-toggler').click();
0
votes

If you have scrolling problems after using the jQuery solution described above, e.g.

$('.navbar-collapse').collapse('toggle');

then this is caused by Bootstrap adding the CSS class overlay-active in the parent element. This can even go up to your body element.

To solve this you have to remove this class:

<script type="text/javascript">
    $(document).ready(function(){

        $('.nav-item').click(function(){
            $('.overlay-active').removeClass('overlay-active');
        });

    });
</script>