Armand Niculescu

Armand is a 32 year old designer and programmer employed with Media Division. He has 15 years experience with programming, specializing in scripting languages such as Actionscript, Javascript and PHP. He also does design and photography.

47 responses to “Automatically highlight current page in menu via Javascript”

  1. Richard

    I’ve used similar techniques on web pages.

    Just add window.onload=setPage; to your javascript and it should trigger automatically.

  2. Rob

    Thanks for this brilliant and very useful code – I’ve been looking for this for weeks – a great Christmas present!

    This is a brilliant tool to remote-control ssi variable menu content (for example in Contribute site menus). Allows the contributer to add any menu items using a simple list, yet they still highlight automatically – sweet!

    One extra functionality would be to switch off the current link somehow – any ideas?

  3. Carrot

    This is just what I needed. As mentioned earlier, is there a way to remove the hyperlink from the current page.

    Also, I am looking at using this via SSI, and calling the script from a .js using

  4. Ben Dalziel

    Thanks to Richard for his suggestion that ensures my pages load without errors in the absence of JS.

    Absolutely love this code; it’s saving me so much time!

    I think I found a little bug though and suggest a fix here: http://bendalziel.blogspot.com/2006/07/auto-highlighting-navigation.html

    I’m pretty new to JavaScript so any hints or corrections would be great. I return “x” just because I’m not sure what would be better to return…

    Thanks again

  5. Armand Niculescu

    Thank you for your contribution, Ben!

  6. Geoff

    Thanks for the code. It’s exacly what I was looking for. One question. How would I be able to have multiple links selected on a page, ex. have a sub menu item highlighted? Each of these would be located in different divs. Thanks

  7. Armand Niculescu

    Geoff, you can have the highlighter work simultaneously on different navigation menus, but only if they point to the same page, i.e. you have a top navigation with a link to stuff.html and a left-side navigation also pointing to stuff.html

    In this case, in the setPage() function, duplicate the last line for the new div:

    if (document.getElementById('navbar')!=null)
        setActiveMenu(document.getElementById('navbar').getElementsByTagName('a').extractPageName(hrefString));
    if (document.getElementById('navleft')!=null)
        setActiveMenu(document.getElementById('navleft').getElementsByTagName('a').extractPageName(hrefString));
    }
    

    It can get however a little confusing, especially if you have links to documents with the same name, e.g. index.htm but placed in different folders, e.g. /work/index.htm and /home/index.htm. To cope with this, I rewrote the extractPageName() function but I want to test it more before i publish it.

  8. PDawg

    I’ve used this script on a previous project. Very cool and useful script. One question that I have is how do I get a main menu item to remain highlighted with I click on a sub-menu item? So, for example, “products” is the main menu item and “iPods”, “Cameras”, and “TVs” are my sub-menu items. What I would like to see is for “products” to remain highlighted while I click on “cameras”.

  9. Ahmed G

    Great script thanks! And if some of the pages in your navigation have query strings, then substitute the extractPageName function with:

    function extractPageName(hrefString)
    {
    var arr = hrefString.split(‘.’);
    // Check to see if the url has a query string by searching for the question mark
    var hasquestion=hrefString.indexOf(‘?’);
    if (hasquestion == ‘-1′)
    {
    arr = arr[arr.length-2].split(‘/’);
    return arr[arr.length-1].toLowerCase();
    }
    else
    {
    return arr[arr.length-1].toLowerCase();
    }
    }

    This will allow your links like filename.php?querystring=blabla to be highlighted as well. Well, it works for me anyway.

    Cheers

  10. Armand Niculescu

    @PDawg,

    You can highlight a parent’s link if the menus are nested lists (like http://www.htmldog.com/articles/suckerfish/example/), but I can’t give you very specific directions as I don’t know your exact configuration.

    Anyway suppose you have a hierarchy like
    ul#menu>li>ul#submenu>li>a

    If you look in the javascript code, you’ll see a line
    arr[i].className = 'current';.

    From there, you apply the ‘current’ class to the link itself (the 'a' tag) but you can also apply it (or some other class) to one of its ancestors.

    You can write arr[i].parentNode.parentNode.parentNode.className = 'current'; to apply the ‘current’ class to the 'li' that is part of the 'ul#menu' list.

    I hope it makes sense…

  11. Dan G.

    This is the code I came up with, as you can see it is MUCH shorter

    http://24thwebdesign.freehostia.com/current/current.js

  12. mark

    Great script! This could be just what I have been looking for, however I’m new to all things about web design and I would like to know how this script can be used via a dreamweaver template on a site with 100s of pages with large numbers of pages requiring the same highlighted link in a navigation menu. I need to be able to lock the nav menu into a non-editable region of the template. Can someone please help me?

  13. Armand Niculescu

    Mark, there’s nothing special about using the script within a DW template — actually I wrote it specifically to be used with it. For example http://www.whizz.com uses it with Dreamweaver templates.

    Have a look at the page with View Source to see how it works (I think I’ve also updated the javascript code since I wrote the article).

  14. Alice

    Hello, thanks for the code, is very neat.
    I’m trying to include the java-script and instead to call the setPage() in the page, I have this added to the js:

    window.onload=function(){
    setPage();
    }

    Thanks again! (love the captcha)

  15. Alice

    Also, to make it to work you need to replace
    setActiveMenu(document.getElementById(‘navbar’).getElementsByTagName(‘a’).extractPageName(hrefString));

    with:
    setActiveMenu(document.getElementById(‘navbar’).getElementsByTagName(‘a’),extractPageName(hrefString));

  16. Jeremy

    Thanks for the script! Works great. However, I have a suggestion, related to what Ahmed G said about query strings. It should also be noted that “anchors” at the end of urls also break the script if coming from another page, or simply reloading the page w/ the anchor still attached to the url (i.e. blah.com/page.htm#end), the same as query strings do. Here’s a simple fix I wrote to address both in only 2 lines of code, plus slightly altering one of your existing lines of code:

    New code in bold
    Altered code in italics


    function extractPageName(hrefString)
    {
    var hrefString = hrefString.split('#');
    var hrefString = hrefString[0].split('?');

    var arr = hrefString[0].split('/');

    return (arr.length<2) ? hrefString : arr[arr.length-2].toLowerCase() + arr[arr.length-1].toLowerCase();
    }

    Please note, “if statements” to check for “?” and “#” are unnecessary in my code, because if they do not exist, the result of the split is simply a single item array. Much easier than doing the checks and there are no errors either. Hope that’s helpful for someone.

    [Armand: Excellent post, Jeremy. Thanks!]

  17. Tawan

    very good script
    Thanks you guys so much

  18. Meme11

    Administrator, you’re the man!! This works like a charm! And a million “thank you’ to Ahmed G, who’s solution for query string pages work great.
    So if you have dynamicaly generated pages like this for example: – browse.php?c=1 – you have to modify the “extractPageName” function in highlight.js with Ahmed G’s mod:
    [code]
    function extractPageName(hrefString)
    {
    var arr = hrefString.split('.');
    // Check to see if the url has a query string by searching for the question mark
    var hasquestion=hrefString.indexOf('?');
    if (hasquestion == '-1')
    {
    arr = arr[arr.length-2].split('/');
    return arr[arr.length-1].toLowerCase();
    }
    else
    {
    return arr[arr.length-1].toLowerCase();
    }
    }
    [/code]
    for this to work only in current page, otherwise all pages like
    browse.php?c=# (where # is the number of the page) will be highlighted.
    Hope this helps.

  19. Lists

    Great tips.
    It’s always a pain marking an active page, this looks a great solution.
    I’m going to try it right now.

    Thanks!

  20. Paul Carlisle

    This is a nice solution, but as Ben Dalzeil pointed out it suffers from a problem: it fails for pages referenced indirectly through their index.html file.

    If I invoke the page http://www.mydomain.org/topic/index.html via http://www.mydomain.org/topic/, HREF doesn’t tack on ‘index.html’; it simply passes along the URL with the slash-suffixed pathname. Unfortunately, there doesn’t seem to be any way to extract the explicit filename using JavaScript, at least not that I’m aware of.

    My not very elegant solution is to maintain a list of objects, each of which stores the title and absolute URL of the page in question. I can then compare the titles, as I can extract document.title with ease – as long as I’m careful to name them the same in both places, which is certainly a shortcoming of this approach.

    Using some sort of modified Sitemap that would be read and used to set both the stored titles and the page titles themselves would solve this problem, but suddenly this project is ballooning in size…

  21. Tom

    Was attempting to do this with .NET but it was getting messy. This is a fantastic bit of code :)

    Only problem I’m having so far is:

    I’m on a page called /about/index.aspx
    So where I have “about home” – it highlights it nicely.

    However, in my navigation I have a link to /contact/index.aspx

    And it highlights that as well. So I have two highlighted items.

    Now, it’s not a major problem as I just removed the “index.aspx” out of the link to /contact.

    But just thought I’d let you all know.

  22. gap tooth clan

    I think this is a great function, would have had to code it myself if not found it.

    I have just been investigating jquery looks pretty good, I am sure it could do this more efficiently.

    Could do with a load handler and an add class function rather than just changing the class to whatever.

    But good work all round

  23. Josiah Platt

    This is such a brilliant code snippet. I love simple / smart code. Thank you.

    : huggle :

  24. Rui Pedro

    :)
    take me some time to make the id=NAV :)

    worked gr8
    ty

  25. Brian

    As Ben Dalzeil and Paul Carlisle pointed out above, this doesn’t work on “index” pages that reside in different directories (such as /about/, or /contact/ etc.). Great code otherwise, and I’m glad to see this topic being tackled!

    Does anyone have a recommended solution?

  26. Strother

    I have the same problem as Tom – 4 posts up. I use Zope and I am forced to have links with a forward slash – like

    Club/index_html
    Sailing/index_html

    and the java script doesn’t separate them – and both links are highlighted when you are on one or the other. If I could make the links

    Club.index_html
    Sailing.index_html

    It would work fine. Can you or someone suggest how the javascript should be modified to work with the forward slashes and distinguish between the links. Thanks.

  27. Kasun

    Thanks a lot, I was thinking weeks to do it without any satisfiable solution, Thanks again for you all.

  28. Cory

    Great script! But could it be modified for image-based active states where you have different graphics files to load for each hover/stick state? For instance if I wanted it to be a different background image for each class as in the following …

    ul#menu li.home a {
    background: url(images/menu_home.png) 0 0 no-repeat;
    width: 67px;
    }
    ul#menu li.locations a {
    background: url(images/menu_locations.png) 0 0 no-repeat;
    width: 119px;
    }
    ul#menu li.about a {
    background: url(images/menu_about.png) 0 0 no-repeat;
    width: 115px;
    }
    ul#menu li.contact a {
    background: url(images/menu_contact.png) 0 0 no-repeat;
    width: 136px;
    }

    I’m assuming the .js file would have to be modified to discover which page the specific class is on, then apply that specific class using the CSS file. So instead of one class for the active state, there might be several from which to choose.

    Thanks in advance!

  29. Qatar Boy

    the javascript example worked right out of the box. thanks a lot as you saved a ton of time. cheers, qatar boy

  30. Eugen

    Thank you for making this available for all of us.
    I’ve been looking for something like this for quite some time.

    All the best!

  31. Joshua Dyball

    This is great technique. It’s a shame about it’s one achilles heel of not showing the current page (home) when browsing the root domain (rather than index.html). Is there no easy solution for this?

  32. James

    Thats a nice little script, I found this. My only issue with it is that is searches the whole page but it works.

    <script type="text/javascript">
    var anchors = document.getElementsByTagName("a");
    var uri = encodeURI(window.location.href).toLowerCase();
    for(var i=0, n=anchors.length; i<n; ++i) {
    if(uri==encodeURI(anchors[i].href).toLowerCase()) {
    anchors[i].style.className += " current ";
    break;
    }
    }
    </script>

    source can be found by searching google with
    “javascript dynamically highlight current page”

    first result

    Very happy, am always dealing with php generated navigation and have no control over the html. Now I kinda do!!

  33. Daniel P

    I am struggling with hrefs having “#” as only value (a href=”#” onclick=”javascript:showEtc…).

    Thanks a lot for a beautiful solution! I have a problem though:

    When I use Armand’s original code, the page on reloading switches between highlighting links to:
    “current_site.html” (as the browser address field displays: current_site.html)
    and highlighting links to:
    “#” (as the browser address field displays: current_site.html#)

    When I use Jeremy’s revised code I get highlighted links for both “#” and “current_site.html”, no matter what is in the browser address field, no matter reloading or not.

    I don’t want any links to “#” highlighted in any condition. In my n00b javascript eyes, it looks like Jeremy’s revised code should do the trick, but it doesn’t. Anyone has an idea on what to do?

  34. inzzzomnia

    How would i go about if i’d like my menu to in a seperate file (external)?

  35. Bill Dashfield

    Nice little script – just what I was looking for.

    One little mistake, I think (also what Alice was trying to say?):

    In your explanation you say ‘all links that are contained in the navigation bar (any tag with id=”navbar”)’
    but your code says:

    if (document.getElementById(“nav”)!=null) setActiveMenu(document.getElementById(“nav”).getElementsByTagName(“a”)

    To find your navigation links, I think the “nav” in the code should be “navbar”:
    if (document.getElementById(“navbar”)!=null) setActiveMenu(document.getElementById(“navbar”).getElementsByTagName(“a”)

    Thanks Bill

  36. ghprod

    Hi, how to get current page but in PHP without JS?

    regards

    thanks

  37. Tim

    First of all…THANKS a bunch, this is exactly what I’ve been looking for.
    I’m sure I’m missing something on this. But I’m not able to figure out how to get the parent LI to highlight even if it’s a child of that li. So for example if there is any li tags that are underneath the parent to still highlight the parent and not the current li. http://www.capellnet.com/SITETEMPLATE

    Here’s the code I have currently have for the menu.

    MenuItem 1

    MenuItem 1.1
    MenuItem 1.2
    MenuItem 1.3

    MenuItem 2

    MenuItem 2.1
    MenuItem 2.2
    MenuItem 2.3
    MenuItem 2.4
    MenuItem 2.5

    MenuItem 3
    MenuItem 4
    MenuItem 5

    setPage()

    Here’s the JS info:
    arr[i].className = “current”;
    arr[i].parentNode.className = “current”;

    Here’s the CSS for the menu section:
    /***TOP NAVMENU***/
    #jsddm {
    float: left;
    width: 922px;
    height: 25px;
    background-image: url(../images/nav1.gif);
    background-repeat: repeat-x;
    margin:0;
    padding:0;
    }
    #jsddm li {
    float:left;
    list-style:none;
    }
    #jsddm li a {
    display: block;
    padding: 5px 12px;
    text-decoration: none;
    background-image: url(../images/nav1.gif);
    background-repeat: repeat-x;
    font-family: Verdana, Geneva, sans-serif;
    font-size: 12px;
    font-weight: bold;
    color: #666;
    width: 91px;
    white-space: nowrap;
    }
    #jsddm li ul {
    margin: 0;
    padding: 0;
    position: absolute;
    visibility: hidden;
    }
    #jsddm li ul li {
    float: none;
    display: inline;
    }
    #jsddm li ul li a {
    width: auto;
    border-bottom: 1px solid #CCC;
    }
    #jsddm li a:hover { background-image:url(../images/nav2.gif);background-repeat:repeat-x;}
    #jsddm li ul li a:hover{background-image:url(../images/nav2.gif);background-repeat:repeat-x;}
    #jsddm li a.current {background-image:url(../images/nav3.gif);background-repeat:repeat-x;color:#FFF;}

    Thanks for any light you can shed on this… :-)

  38. Tim

    How do you get the parent li to highlight instead of the children li’s in a list…here’s what I have
    http://www.capellnet.com/SITETEMPLATE

  39. website development

    I am building a new website for commensus.co.uk and was looking for a similar solution. thanks a lot for this tutorial the CSS+Javascript solution rocks

  40. Chris Wheeler

    Thanks very much for this.  A great piece of code. I may modify it slightly for my use, but nevertheless it was a great help.

  41. Juan

    Thanks much for your code! :)

  42. Juan

    With regards to the question of whether I can highlight two different links on the same page, for example, if I have a main navigation call “about us” and a left navigation call “vision and mission”, how do I get both “about us” and “vision and mission” highlighted. Take it that “aboutus.html” and “visionandmission.html” are in the same folder? Thanks. :)

Leave a Reply