Add Active Navigation Class Based on URL

Ideally you output this class from the server side, but if you can't...

Let's say you have navigation like this:

<nav>
	<ul>
		<li><a href="/">Home</a></li>
		<li><a href="/about/">About</a></li>
		<li><a href="/clients/">Clients</a></li>
		<li><a href="/contact/">Contact Us</a></li>
	</ul>
</nav>	

And you are at the URL:

http://yoursite.com/about/team/

And you want the About link to get a class of "active" so you can visually indicate it's the active navigation.

$(function() {
  $('nav a[href^="/' + location.pathname.split("/")[1] + '"]').addClass('active');
});

Essentially that will match links in the nav who's href attribute begins with "/about" (or whatever the secondary directory happens to be).

Comments

  1. User Avatar
    Mike
    Permalink to comment#

    I’ve been struggling trying to get something like this to work on a templated HTML website (server side CSS updating not available). The structure of the menu is a little more complex than your example. Would your CSS trick work for this structure? If so, PLEASE enlighten me because I’m stuck.

  2. User Avatar
    mehdi
    Permalink to comment#

    Thanks for every things

  3. User Avatar
    Mark Johnson
    Permalink to comment#

    Danke Chris! Simple, clear and slick. High five!

  4. User Avatar
    Leon Gaban
    Permalink to comment#

    Thanks! Been looking for something like this for a while now :)

  5. User Avatar
    Don
    Permalink to comment#

    Works like a charm with one exception. One the home page the class is added to all the links. The all start with /. Any help would be appreciated.

    • User Avatar
      Don
      Permalink to comment#

      Simple fix: Don’t use the script on the home page file. Duh. :)

    • User Avatar
      Michel
      Permalink to comment#

      Try replacing the hrefˆ= with href$=

      ˆ= value begins with
      $= value ends with

    • User Avatar
      Peter
      Permalink to comment#

      This is what I did to accommodate the ‘home’ page or ‘index’.

      if (location.pathname !== '/') {
      $("a[href*='" + location.pathname + "']").addClass("current");
      } else {
      var home = document.getElementById("home").getElementsByTagName('a')[0];
      home.className = 'current';
      }

      Hope that helps.

    • User Avatar
      Justin
      Permalink to comment#

      I don’t have “/” in my navigation, so the code added “active” class to all my links on the home page. In my case, I did the following so my “/” path doesn’t run the code:

      $(function() {
          if ((location.pathname.split("/")[1]) !== ""){
              $('nav a[href^="/' + location.pathname.split("/")[1] + '"]').addClass('active');
          }
      });
      
  6. User Avatar
    bgdbraba

    Indeed. As well that pages that are called for example /about en /aboutsome are also both ‘active’ when you press ‘about’. Any solution for this, like a sort of exact matching?

  7. User Avatar
    John
    Permalink to comment#

    Hi,

    I couldn’t get the above selector to work, but used this (php specific solution) to match the current URL.

    Hope this helps someone (haven’t thoroughly tested so might have some limitations/unexpected results).

    $(‘nav a[href=””]’).addClass(‘active’);

    • User Avatar
      John
      Permalink to comment#

      My comment above stripped out PHP, so I will adjust, and you will have to use common sense when using it.
      $('nav a[href="<?php echo "http://$_SERVER[HTTP_HOST]$_SERVER[REQUEST_URI]"; ? >"]').addClass('active');

  8. User Avatar
    mlotfi
    Permalink to comment#

    Hi,
    I am a newbie here, can you please provide a working example ?
    Thanks.

  9. User Avatar
    Luke Etheridge
    Permalink to comment#

    Hi there guys – does anyone know how this is possible with the absolute url (whole url)?

    I’m sure this is an easy thing to do but I don’t really know where to start with the code…

    Thanks,
    Luke

    • User Avatar
      ArtyPea
      Permalink to comment#
      $(function() {
          var nav = document.getElementById("sticky"),
              anchor = nav.getElementsByTagName("a"),
              current = window.location;
      
          console.log("anchor = ",anchor,"current = ",current);
      
          for (var i = 0; i < anchor.length; i++) {
          if(anchor[i].href == current) {
              anchor[i].className = "active";
      
          }
      
      }
      });
      
  10. User Avatar
    Ramesh Chowdarapally
    Permalink to comment#

    Chris, can you provide a small demo for this?

  11. User Avatar
    Ashok
    Permalink to comment#

    Yes This is Useful…..

  12. User Avatar
    Brian
    Permalink to comment#

    Two quick questions:

    If my url is dynamic, how should I adjust the anchor part of the javascript?
    Is there a pure css method for the active state shown above? Just thought i’d ask. I would use the hover effect for non-js viewers in case anyone should want to know.

  13. User Avatar
    Wesley
    Permalink to comment#

    My situation is similar but different. I need to target a specific nav element with the active class when a non-child document is active. Any ideas on how to do this?

  14. User Avatar
    Vita
    Permalink to comment#

    I implemented a slightly different approach. I try to find the best match for the url and current location. Created a jQuery plugin for this https://github.com/Vitaa/ActiveNavigation

    • User Avatar
      Anthony Candaele
      Permalink to comment#

      works like a charm Thanks a lot!

    • User Avatar
      Kenneth Hodges
      Permalink to comment#

      Hello!

      I found a routine to set active (current) class on my shared menu, but I need to modify it to set the parent link only, and not the ‘closest’ link. It works great on menu items with no sub menus, but when a sub menu item is clicked, there is not indication on the main menu after page load. (the code I need to modify is below)

      (function( $ ) {
          $.fn.activeNavigation = function(selector) {
              var pathname = window.location.pathname
              var extension_position;
              var href;
              var hrefs = []
              $(selector).find("a").each(function(){
                  // Remove href file extension
                  extension_position = $(this).attr("href").lastIndexOf('.');
                  href = (extension_position >= 0) ? $(this).attr("href").substr(0, extension_position) : $(this).attr("href");
      
      <code>        if (pathname.indexOf(href) > -1) {
                  hrefs.push($(this));
              }
          })
          if (hrefs.length) {
              hrefs.sort(function(a,b){
                  return b.attr("href").length - a.attr("href").length
              })
            hrefs[0].closest('li').addClass("current")
          }
      }; })(jQuery);
      
  15. User Avatar
    Jonno

    Any chance you could show how to do this in the PHP please?

  16. User Avatar
    George v
    Permalink to comment#

    TKX
    Vita

  17. User Avatar
    barrett fullerton
    Permalink to comment#

    Quick update not sure if its been said, but if your looking to use this as well as keep a home link as a “/”

    $(function() {
        if ((location.pathname.split("/")[1]) !== ""){
            $('nav a[href^="/' + location.pathname.split("/")[1] + '"]').addClass('active');
        }
        else {
        $('nav li.home-link a').addClass('active');
        }
    });
    

    Just do something to differentiate your home li or a tag, like in the else.

  18. User Avatar
    Alio

    Great Respect! Very helped me!

  19. User Avatar
    Esen
    Permalink to comment#

    I have this solution with vanilla JS and I have a problem. The hash(#) in the url changes slower than the active clases. So I click on the first link and nothing happends, then I click on the second one and the first one got the active class.

    <script>
        document.addEventListener("DOMContentLoaded", function(event) { 
            console.log("Oh, Hello.");
    
            //Preselect all the links 
            var links =  document.querySelectorAll('.nav-class-link');
    
            // Connect the links event-click with the event handler
            for (var i = links.length - 1; i >= 0; i--) {
                links[i].addEventListener('click', updateLinksActiveState);
            }
    
            //Event Handler
            function updateLinksActiveState(){  
                //Check for the active one
                for (var i = links.length - 1; i >= 0; i--) {
                    if(links[i].href.split("#")[1] == location.hash.split("#")[1]){
                        links[i].classList.add('active');
                    }else{
                        links[i].classList.remove('active');
                    }
                }
            }
        });
        </script>
    
  20. User Avatar
    neeta
    Permalink to comment#

    Hi,

    I have a reverse situation.

    What if don’t want the parent menu to be highlighted when its child (submenu item ) is active?

    Eg:

    About us – No color
    – Link 1
    – Link 2 (Currently active) : want it in some color

    Any clue ?

    Many thanks

    • User Avatar
      Aryan Malik
      Permalink to comment#

      Hey try this one.

      $(function() {
        var url = location.origin + location.pathname;
        $('nav a[href^="' + url + '"]')
          .css({
              'background': '#fff',
              'color' : '#c02f2f'
            });
      });
      
  21. User Avatar
    Aryan Malik
    Permalink to comment#

    Hey i try this peace of codes and its working great for me…

    $(function() {
      var url = location.origin + location.pathname;
      $('nav a[href^="' + url + '"]')
        .closest('li')
        .addClass('active');
    });
    
    • User Avatar
      Bekzat Sadykov
      Permalink to comment#

      Thank you Aryan. Your code works very well for me.

  22. User Avatar
    Huy
    Permalink to comment#

    It worked !! Thank you for your share

  23. User Avatar
    Luis
    Permalink to comment#

    Great post and tip. I’ll leave my contribution here. For those who are having problems matching URLs with parameters, here’s the solution (the code is adding the CLASS to the parent LI tag and not the A tag as the original post):

    $(function() {
    var url = window.location.href; url = url.replace(/^.*\/\/[^\/]+/, ”);
    $(‘nav a[href$=”‘ + url + ‘”]’).closest(‘li’).addClass(‘active’);
    });

Leave a Comment

Posting Code!

You may write comments in Markdown. This makes code easy to post, as you can write inline code like `<div>this</div>` or multiline blocks of code in triple backtick fences (```) with double new lines before and after.

Code of Conduct

Absolutely anyone is welcome to submit a comment here. But not all comments will be posted. Think of it like writing a letter to the editor. All submitted comments will be read, but not all published. Published comments will be on-topic, helpful, and further the discussion or debate.

Want to tell us something privately?

Feel free to use our contact form. That's a great place to let us know about typos or anything off-topic.

icon-anchoricon-closeicon-emailicon-linkicon-logo-staricon-menuicon-nav-guideicon-searchicon-staricon-tag