Question

On the Bootstrap website the subnav matches up with the sections and changes background color as you or scroll to the section. I wanted to create my own menu without all the background colors and everything, however, I changed my CSS to be similar but when I scroll down or click on the menu item the active class does not switch. Not sure what I'm doing wrong.

HTML:

<ul class="menu">
    <li class="active"><a href="#">Home</a></li>
    <li><a href="#about">About Us</a></li>
    <li><a href="#contact">Contact</a></li>
</ul>

CSS:

.menu {list-style:none;}
.menu > li {float: left;}
.menu > li > a {color:#555;float: none;padding: 10px 16px 11px;display: block;}
.menu > li > a:hover {color: #F95700;}
.menu .active > a, .menu .active > a:hover {color:#F95700;}

I checked the files; jQuery, bootstrap.js and bootstrap.css are all linked properly. Do I have to add some additional jQuery in or am I missing some CSS to get the active to switch like the subnav menu on their site?

Was it helpful?

Solution

In order to switch the class, you need to perform some JavaScript.

In jQuery:

$('.menu li a').click(function(e) {
  var $this = $(this);
  if (!$this.hasClass('active')) {
    $this.addClass('active');
  }
  e.preventDefault();
});

In JavaScript:

var menu = document.querySelector('.menu');
var anchors = menu.getElementsByTagName('a');

for (var i = 0; i < anchors.length; i += 1) {
  anchors[i].addEventListener('click', function() { clickHandler(anchors[i]) }, false);
}

function clickHandler(anchor) {
  var hasClass = anchor.getAttribute('class');
  if (hasClass !== 'active') {
    anchor.setAttribute('class', 'active');
  }
}

I hope this helps.

OTHER TIPS

This is what I ended up with since you have to clear the others as well.

$('.navbar li').click(function(e) {
    $('.navbar li.active').removeClass('active');
    var $this = $(this);
    if (!$this.hasClass('active')) {
        $this.addClass('active');
    }
    e.preventDefault();
});

this is my code for handling twitter bootstrap navigation list:

$(document).ready(function () {
        $('ul.nav > li').click(function (e) {
            e.preventDefault();
            $('ul.nav > li').removeClass('active');
            $(this).addClass('active');                
        });            
    });

I use 2 1-liners, depending on how my nav is structured

Just make sure that none of your links have active class to start.

actual links

If your nav links are on separate HTML files (like a layout template in express.js that has a menu), you can do this:

$('ul.nav > li > a[href="' + document.location.pathname + '"]').parent().addClass('active');

hash links

If they are hashes, do this:

$('ul.nav > li > a[href="' + document.location.hash + '"]').click(function(){  $('ul.nav > li').removeClass('active'); $(this).parent().addClass('active'); });

If you don't want to scroll on hash-click, return false:

 $('ul.nav > li > a[href="' + document.location.hash + '"]').click(function(){  $('ul.nav > li').removeClass('active'); $(this).parent().addClass('active'); return false; });

Looking at some of the other answers, if you want the webpage to scroll down to that section when a side menu is clicked then you don't want to preventDefault.

Additionally, you only need to remove the current active class and add a new one not search through all li's. You also want the code to not do anything when the list item you've selected is already active—not needlessly add and remove the same active class. Lastly you should put your event listener on the a element not the li as it has an easier time of triggering a click event on iPhones and tablets, etc. Could also use .delegate so you don't have to wait for a DOM ready event. So in the end I'd do something like this (I assume you've preloaded jQuery):

$('body').delegate('.menu li a', 'click', function(){
    var $thisLi = $(this).parents('li:first');
    var $ul = $thisLi.parents('ul:first');
    if (!$thisLi.hasClass('active')){
        $ul.find('li.active').removeClass('active');
        $thisLi.addClass('active');
    }
});

I suggest this code :

 <script>
      var curentFile = window.location.pathname.split("/").pop();
      if (curentFile == "") curentFile = "Default.aspx";
      $('ul.nav > li > a[href="' + curentFile + '"]').parent().addClass('active');
 </script>

It's work like a charm .

I did something different to solve this (fyi, i'm a complete html/css/js amateur).

Each of my navbar buttons goes to a new page. so, in each page's html, i put something like this at the bottom:

<script type="text/javascript">
    $(document).ready( function(){
       $("#aboutButton").removeClass("active");
    });

    $(document).ready( function(){
       $("#dashboardButton").addClass("active");
    });
</script>

That got it working right away for me.

P.S. I tried the accepted answer but had no luck as it would also need to remove the 'active' class from the currently active button to truly 'switch' over. I'm sure it's possible, but again, I'm pretty new to this stuff.

Tested and it works fine.

    $('.navbar li').click(function(e) {
        $('.navbar li.active').removeClass('active');
        var $this = $(this);
        if (!$this.hasClass('active')) {
            $this.addClass('active');
        }

    });

  <ul class="nav navbar-nav">
            <li class="active"><a href="#">Home</a></li>
            . . . 
  </ul>

anyone having problems with this using jsp, watch your packages.

document.location.pathname gave me: /packagename/index.jsp

but my href in my navbar called just index.jsp

So to edit konsumer's answer:

$(document).ready(function() {
   var string = document.location.pathname.replace('/Package Name/','');
   $('ul.nav > li > a[href="' + string + '"]').parent().addClass('active');
} );

I tried some of the top answers above, it works for ".active" class, but the links not working well, it still stays on the current page. Then I tried this:

var url = window.location;
// Will only work if string in href matches with location
$('ul.nav a[href="' + url + '"]').parent().addClass('active');
// Will also work for relative and absolute hrefs
$('ul.nav a').filter(function() {
    return this.href == url;
}).parent().addClass('active');

I found it here: Twitter Bootstrap add active class to li

<ul class="main-menu">
    <li><a href="~/Cases/Index"><i class="fa fa-font fa-fw"></i><span class="text">Audit Case</span></a></li>
    <li><a href="~/Cases/Auditplan"><i class="fa fa-font fa-fw"></i><span class="text">Audit Plan</span></a></li>
    <li><a href="~/Cases/Auditreport"><i class="fa fa-font fa-fw"></i><span class="text">Audit Report</span></a></li>
    <li><a href="~/Cases/Company"><i class="fa fa-font fa-fw"></i><span class="text">Company Details</span></a></li>
</ul>

<script>
$(function(){
  $('.main-menu li > a[href="' + document.location.pathname + '"]').parent().addClass('active').siblings().removeClass('active');
})
</script>

Add to your JavaScript:

$(".menu li").click(function(e) {
    $(".menu li").removeClass("active");
    $(this).addClass("active");
    e.preventDefault();
});

This is getting pretty old and clustered with answers, but I took the top answer and made it better. The top answer only works if there's one on the page. This scopes it to removing active from sibling elements and adding it to the one you clicked.

I also added the class nav-toggle so that it doesn't interfere with things that already have bootstrap js attached.

$('.nav.nav-toggle li').click(function(e) {
  var $this = $(this);
  $this.siblings().removeClass('active');
  if (!$this.hasClass('active')) {
      $this.addClass('active');
  }
  e.preventDefault();
});
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top