45

I'm trying to add an active class (i.e. class="active") to the appropriate menu list item based upon the page it is on once the page loads. Below is my menu as it stands right now. I've tried every snippet of code I could find in this regard and nothing works. So, can someone please explain simply where and how to add in javascript to define this task?

<ul id="nav">
    <li id="navhome"><a href="home.aspx">Home</a></li>
    <li id="navmanage"><a href="manageIS.aspx">Manage</a></li>
    <li id="navdocso"><a href="docs.aspx">Documents</a></li>
    <li id="navadmin"><a href="admin.aspx">Admin Panel</a></li>
    <li id="navpast"><a href="past.aspx">View Past</a></li>
</ul>

Here is an example of the javascript that I'm putting in my head tag in my site master. What am I doing wrong?

$(document).ready(function () {
    $(function () {
        $('li a').click(function (e) {
            e.preventDefault();
            $('a').removeClass('active');
            $(this).addClass('active');
        });
    });
});
Penny Liu
  • 15,447
  • 5
  • 79
  • 98
slybitz
  • 689
  • 1
  • 7
  • 18
  • 2
    Not related to **OP** But for simple use cases with **Bootstrap 4** `$(function () { $(\`.nav-link[href="${location.pathname}"]\`).parent().addClass("active"); });` – Givi Apr 12 '20 at 07:29

25 Answers25

78

The reason this isn't working is because the javascript is executing, then the page is reloading which nullifies the 'active' class. What you probably want to do is something like:

$(function(){
    var current = location.pathname;
    $('#nav li a').each(function(){
        var $this = $(this);
        // if the current path is like this link, make it active
        if($this.attr('href').indexOf(current) !== -1){
            $this.addClass('active');
        }
    })
})

There are some cases in which this won't work (multiple similarly pointed links), but I think this could work for you.

Rob M.
  • 35,491
  • 6
  • 51
  • 50
  • 1
    Thank you. Using this as well as adding a "/" to the front of my links (e.g. /home.aspx vs home.aspx) corrected the issue. – slybitz Nov 19 '13 at 16:58
  • @RobM. what if you have a ul within a ul - how would you set the active class on the top level link? – mjcoder Oct 24 '14 at 09:05
  • 1
    @MJCoder `$this.parents('.target-parent-selector').addClass('active')` – Rob M. Oct 24 '14 at 18:49
  • @RobM. any chance of a JSFiddle? – mjcoder Oct 29 '14 at 13:55
  • @MJCoder with this code, it is setting active to the link tag, how do you get it to set active to a class in the li tag – CodaBae Feb 23 '20 at 21:34
  • How can we achieve this in Angular 8? I have tried using routerLinkActive but it's not working. Can someone provide an insight into this? – Shobhit Mar 13 '20 at 06:30
  • Hi, one thing /blog, and /blogAds urls, How can I do for this? – LoveCoding Apr 04 '20 at 09:23
  • @CodaBae You can use `$this.closest('li').addClass('active')` or if `a` is child of `li` then `$this.parent().addClass('active')` – Harry B Aug 05 '21 at 10:22
25

    jQuery(function($) {
     var path = window.location.href; // because the 'href' property of the DOM element is the absolute path
     $('ul a').each(function() {
      if (this.href === path) {
       $(this).addClass('active');
      }
     });
    });
.active, a.active {
    color: red;
}
a {
    color: #337ab7;
    text-decoration: none;
}
li{
    list-style:none;
}
<h3>Add Active Navigation Class to Menu Item</h3> 

    <ul>
     <li><a href="/">Home</a></li>
     <li><a href="/about/">About</a></li>
    </ul> 

<h2><a href="http://www.sweet-web-design.com/examples/active-item/active-class.html">Live Demo</a></h2>
Figar Ali
  • 826
  • 1
  • 9
  • 17
18

With VANILLA plain JavaScript

(function () {
    var current = location.pathname.split('/')[1];
    if (current === "") return;
    var menuItems = document.querySelectorAll('.menu-item a');
    for (var i = 0, len = menuItems.length; i < len; i++) {
        if (menuItems[i].getAttribute("href").indexOf(current) !== -1) {
            menuItems[i].className += "is-active";
        }
    }
})();
Panagiotis Koursaris
  • 3,794
  • 4
  • 23
  • 46
  • 3
    Works perfectly except it removes all existing classes in the 'a' element in favor of "is-active". To work around this I changed line 7 in your snippet to `menuItems[i].className += " is-active";` which seems to have done the trick. – SeRosiS Sep 28 '20 at 22:07
6

ES6 version, that works properly in cases when your link is to "/products" and you have subroutes, like: "/products/new", "/products/edit", etc.

let switchNavMenuItem = (menuItems) => {

    var current = location.pathname

    $.each(menuItems, (index, item) => {

        $(item).removeClass('active')

        if ((current.includes($(item).attr('href')) && $(item).attr('href') !== "/") || ($(item).attr('href') === "/" && current === "/")){
            $(item).addClass('active')
        }
    })
}

$(document).ready(() => {   
    switchNavMenuItem($('#nav li a, #nav li link'))
})
Sergey Bezugliy
  • 580
  • 7
  • 23
3

If your menu need add the active class in li, you need use this code above.

$(function($) {
  let url = window.location.href;
  $('nav ul li a').each(function() {
    if (this.href === url) {
      $(this).closest('li').addClass('active');
    }
  });
});
3

None of the above solutions worked for me. Finally this javascript solution worked.

<script>
function setActive() {
  linkObj = document.getElementById('premier-topnav').getElementsByTagName('a');
  for(i=0;i<linkObj.length;i++) { 
    if(document.location.href.indexOf(linkObj[i].href)>=0) {
      linkObj[i].classList.add("active");
    }
  }
}

window.onload = setActive;
</script>    

premier-topnav is the id of navbar div.
.active class is defined as:

#premier-topnav .active {
    color: brown;   
}
Networker
  • 41
  • 2
  • Better use ```document.location.pathname === linkObj[i].getAttribute('href')``` otherwise you will have hard time to deal with the home page. – Adam Jul 11 '20 at 07:56
  • Thank you for this answer. I'm learning JS and spent few hours to get some results but thanks to your snippet I could find a right direction. @Adam could you please explain your suggestion? – ironixx Oct 31 '21 at 21:23
2
$(function() {
    var CurrentUrl= document.URL;
    var CurrentUrlEnd = CurrentUrl.split('/').filter(Boolean).pop();

    $( ".top-menu li a" ).each(function() {
          var ThisUrl = $(this).attr('href');
            var ThisUrlEnd = ThisUrl.split('/').filter(Boolean).pop();
            if(ThisUrlEnd == CurrentUrlEnd)
            $(this).addClass('active')
        });
    });
A.moizRiaz
  • 31
  • 3
2

This on page JS code is a 100% working put your id and enjoy it.

   <script src="https://code.jquery.com/jquery-3.3.1.js"></script>
   <script>
   $(document).ready(function() {

            var CurrentUrl= document.URL;
            var CurrentUrlEnd = CurrentUrl.split('/').filter(Boolean).pop();
            console.log(CurrentUrlEnd);
            $( "#lu-ID li a" ).each(function() {
                  var ThisUrl = $(this).attr('href');
                  var ThisUrlEnd = ThisUrl.split('/').filter(Boolean).pop();

                  if(ThisUrlEnd == CurrentUrlEnd){
                  $(this).closest('li').addClass('active')
                  }
            });

   });

Abdel
  • 21
  • 1
1
var cururl = window.location.pathname;
var curpage = cururl.substr(cururl.lastIndexOf('/') + 1);
var hash = window.location.hash.substr(1);
if((curpage == "" || curpage == "/" || curpage == "admin") && hash=="")
{
//$("nav .navbar-nav > li:first-child").addClass("active");
}
else
{
$(".topmenu li").each(function()
{
    $(this).removeClass("active");
});
if(hash != "")
$(".topmenu li a[href*='"+hash+"']").parents("li").addClass("active");
else
$(".topmenu li a[href*='"+curpage+"']").parents("li").addClass("active");
}
1

Rob.M got it right.

I'm just going to post my solution since his didn't really work for me. i have a small change in comparison to him. assuming you have different paths to each link.

(function() {
    var current = location.pathname;
    $('#navbar ul li a').each(function() {
        var $this = $(this); 

        // we check comparison between current page and attribute redirection.
        if ($this.attr('href') === current) {
            $this.addClass('active');
        }
    });
})();
Haim
  • 61
  • 1
  • 7
1

This worked perfectly for me.

$(function($) {
 let url = window.location.href;
  $('nav ul li a').each(function() {
   if (this.href === url) {
   $(this).addClass('active');
  }
 });
});
David Jones
  • 106
  • 3
1

This should do your job in one liner.

document.querySelector(`a[href^='${location.pathname.split('/'[1])}']`).className = 'active'
Softec
  • 125
  • 8
1

I know it been quite a while this question was asked. Here is the answer which will work without jQuery:

var activeNavlink = document.querySelectorAll('nav a[href^="/' + location.pathname.split("/")[1] + '"]');
activeNavlink[0].classList.add('active');

Hope this helps.

Abhay Shiro
  • 3,431
  • 2
  • 16
  • 26
1

If you want for master page in asp .net just put this code inside body tag

 <script type="text/javascript">
    jQuery(function ($) {
        var path = window.location.href; // because the 'href' property of the DOM element is the absolute path
        $('ul a').each(function () {
            if (this.href === path) {
                $(this).addClass('active');
            }
        });
    });
</script>

Thank you

1

jQuery style:

$('a[href="'+ window.location.href + '"]').css({
  backgroundColor: 'red',
  color: 'white'
})

In first line use this if you have relative links

$('a[href="'+ window.location.path + '"]').css({

Or both

$('a[href="'+ window.location.href + '"], a[href="'+ window.location.path + '"]').css({
Andreas
  • 65
  • 6
1

I know this is late answer but this works ok for me

var links = document.querySelectorAll('li a');

for (link of links) {
    if (window.location.pathname == link.getAttribute('href')) {
        link.classList.add('active')
    } else {
        link.classList.remove('active')
    }
}
Ankit Tiwari
  • 4,438
  • 4
  • 14
  • 41
0
$(function(){

//this returns the whole url

  var current = window.location.href;

  //this identifies the list you are targeting

  $('#nav li a').each(function(){
    var $this = $(this);

    // if the current path is exactly like this link, make it active

    if($this.attr('href') === current){

    //this takes care of ul inside a ul, it opens and make active the selected li
        $this.parents('.dropdown-menu').toggle();
        $this.css('color', 'red');
    }
  })
});
iLuvLogix
  • 5,920
  • 3
  • 26
  • 43
Ossim Julius
  • 151
  • 1
  • 4
  • Hi, welcome to Stack Overflow. When answering a question that already has many answers, please be sure to add some additional insight into why the response you're providing is substantive and not simply echoing what's already been vetted by the original poster. This is especially important in "code-only" answers such as the one you've provided. – chb Feb 06 '19 at 13:05
0

The bellow jquery script will match the manu if the page has any query string parameter as well. This script is helpful for links with nearly same name.

<script>
        //select current menu Item
        $(function () {
            var current = location.pathname.toLocaleLowerCase();
            $('.sidebar li a').each(function () {
                var $this = $(this);
                var href = $this.attr('href');
                href = href.replace(/\?.*/, "").toLocaleLowerCase();
                // if the current path is equal to this link, make it active
                if (href === current) {
                    $this.addClass('active');
                }
            })
        })
    </script>
0

Accessible Version:

Here's an accessible version inspired by rob.

  1. I didn't want to run this script on the homepage so I check if it's the homepage
  2. I check if the link matches the exact page instead of checking if it's included in the path. Or else you would get multiple items in the query.

JS

function activateCurrentPage(menuItems){
    var current = location.pathname;
    if (current !== "/") {
    menuItems.each(function(){
        var $this = $(this);
        if($this.attr('href') === current){
            $this.addClass('active');
            $this.attr('aria-current', 'page');
        }
    });
    };  
}

activateCurrentPage( $('#nav li a') );  

CSS

Then for CSS don't target the active class instead target the aria attribute.

#nav a[aria-current="page"]{
   color:red;
}
Gcamara14
  • 510
  • 4
  • 14
0

Saw somethng wth plain Javascript https://www.youtube.com/watch?v=BI3kNsTruWo&ab_channel=OnlineTutorials Put it in <script> tags after header in my Wordpress site

(function () {
  const currentLocation = location.href;
  console.log(currentLocation);
  const menuItem = document.getElementsByClassName('nav-item');
  const menuLength = menuItem.length
    for ( i = 0; i < menuLength; i++){
    if(menuItem[i].href === currentLocation){
      menuItem[i].className += " active"
    }
}

})();
        <a class="nav-item" href="/ideja/">Ideja</a>
        <a class="nav-item" href="/piesaki-sapni/">Piesaki Sapni</a>
        <a class="nav-item" href="/uznemejiem/">Uzņēmējiem</a>
        <a class="nav-item" href="/sapnu-banka/">Sapņu banka</a>
        <a class="nav-item" href="/sapnus-atbalsta/">Sapņus atbalsta</a>
        <a class="nav-item" href="/99-iedvesmas-stasti/">99 iedvesmas stāsti</a>
        <a id="lv" class="active" href="#">LV</a>
        <a href="javascript:void(0);" class="icon" onclick="openNavbar()">
            <div id="hamburger" class="hamburger "></div>
        </a>
Chirka
  • 31
  • 4
0

i was having troubles where the link to the root would light up if any page was selected when using Networker's example. this will prevent that for the root pae:

function setActive() {
  linkObj = document.getElementById('menu').getElementsByTagName('a');
  for(i=0;i<linkObj.length;i++) { 
    const url = new URL(window.location.href);
    if((document.location.href.indexOf(linkObj[i].href)>=0 && linkObj[i].href != url.protocol+"//"+url.hostname+"/") || document.location.href == linkObj[i].href) {
      linkObj[i].classList.add("active");
    }
  }
}
window.onload = setActive;
kaioker2
  • 297
  • 3
  • 11
0

This Does the Job Done For me... Put this before the ending of body tag

 $(function () {
        var current = location.pathname;
        console.log(current);
        if (current == "/") {
            $('#home').addClass('active'); //#home is the id for root link.
        }
        else {

            $('#navbarCollapse div a').each(function () {
                var $this = $(this);
                // if the current path is like this link, make it active
                if ($this.attr('href').indexOf(current) !== -1) {
                    $this.addClass('active');
                }
            })
        }
    })
Ch Usman
  • 519
  • 6
  • 9
0

Classes can make the life a whole way easier.

css

<nav>
    <ul class="nav-list">
        <li class="nav-list-item"><a class="nav-link nav-link-active" href="index.html">Home</a></li>
        <li class="nav-list-item"><a  class="nav-link" href="about.html">About Me</a></li>
        <li class="nav-list-item"><a  class="nav-link" href="posts.html">Recent Posts</a></li>
    </ul>
</nav>

js

(function() {
    current_page = window.location.href;
    navlinks = document.getElementsByClassName("nav-link");
    active_page = document.getElementsByClassName("nav-link-active")[0];
    if (active_page) {
        active_page.classList.remove("nav-link-active");
    }

    for (i=0; i < navlinks.length; i++) {
        if (navlinks[i].href == current_page) {
            navlinks[i].classList.add("nav-link-active");
            break;
        }
    }
})();
alv2017
  • 752
  • 5
  • 14
0

Below is the solution to add the dynamic active class to the navbar elements.

// first lets get all the navbar elements.
const navElements = document.querySelectorAll(".list");
// creating a function of active navbar item 
const activeLink = (el) => {
        list.forEach((item) => {
         item.classList.remove("active");
         el.classList.add("active");
    });
 };


// attaching the event listener for each element
list.forEach((item) => {
    item.addEventListener("click", () => {
       activeLink(item)
    });
 });
Suraj Rao
  • 29,388
  • 11
  • 94
  • 103
Kashif Ali
  • 187
  • 2
  • 9
  • I faced the issue of how to add dynamically active class to links ? today so when i found the solution i thought i might help others – Kashif Ali May 13 '22 at 16:20
0

For dynamically adding the Active class on li tag on nav bar in the .net MVC project, where the dashboard is having only / in the url, you may try this:

HTML

<ul class="nav">
<li class="nav-item">
    <a class="nav-link" href="/">
        
        <i class="icon-grid menu-icon"></i>
        <span class="menu-title">Home</span>
    </a>
</li>
<li class="nav-item">
    <a class="nav-link" href="/Home/About">
        <i class="icon-monitor menu-icon"></i>
        <span class="menu-title">About</span>
    </a>
</li>
</ul>

JS

<script>
        $(() => {            
            // Get the current URL path and remove the trailing slash if it exists
            var currentPath = window.location.pathname.replace(/\/$/, '');

            // Loop through each "nav-link" element
            $('.nav-link').each(function () {
                // Get the href attribute of the link and remove the trailing slash if it exists
                var linkPath = $(this).attr('href').replace(/\/$/, '');

                // Check if the current path matches the link path
                if (currentPath === linkPath) {
                    // Add the "active" class to the parent "nav-item" element
                    $(this).closest('.nav-item').addClass('active');
                }
            });
        })
    </script>
CSJ
  • 1
  • 1