{"id":424,"date":"2009-04-28T19:53:43","date_gmt":"2009-04-29T00:53:43","guid":{"rendered":"http:\/\/cssnewbie.com\/?p=424"},"modified":"2009-04-28T19:53:43","modified_gmt":"2009-04-29T00:53:43","slug":"using-javascript-to-style-active-navigation-elements","status":"publish","type":"post","link":"https:\/\/cssdeck.com\/blog\/using-javascript-to-style-active-navigation-elements\/","title":{"rendered":"Using JavaScript to Style Active Navigation Elements"},"content":{"rendered":"<p><img decoding=\"async\" loading=\"lazy\" src=\"https:\/\/cssdeck.com\/blog\/wp-content\/uploads\/2009\/04\/active-nav.png\" alt=\"active navigation element\" title=\"active navigation element\" width=\"579\" height=\"125\" class=\"alignnone size-full wp-image-426\" \/><\/p>\n<p>I&#8217;m all about efficiency when I&#8217;m writing web code. Any time I find myself writing the same functionality more than once or twice, I try to consider whether my repeated code could be wrapped into a function of some sort.<\/p>\n<p>Navigation is often one of those areas where I try to improve my efficiency. I like my navigation elements to pull double duty. I want them to:<\/p>\n<ol>\n<li>Show the user <em>where they can go,<\/em> and<\/li>\n<li>Show the user <em>where they currently are.<\/em><\/li>\n<\/ol>\n<p>In other words, I want some sort of visual indication in my navigation that shows my user which section of my site they&#8217;re in. You can see this on the CSS Newbie site: if you click on <a href=\"http:\/\/cssnewbie.com\/toc\/\">the TOC (Table of Contents) link<\/a> in the bar at the top of the page, you&#8217;ll see that link gets special styling when the table of content loads.<\/p>\n<p>Now, I could manually set this on every page using a CSS class. But that&#8217;s inefficient &mdash; depending on the size of my site, I could end up writing dozens or hundreds of lines of one-off code. And why go to all that work, when you could just wrap it all up into a nice JavaScript function?<!--more--><\/p>\n<p>First, I&#8217;ll explain the logic behind my functions &mdash; because they won&#8217;t work equally well for every site. Then I&#8217;ll walk you through a few examples of the code that makes it all happen.<\/p>\n<h3>The Logic<\/h3>\n<p>All of my functions assume a very clean, straightforward directory structure. For example, if you have an About section, a Blog section, and a Contact section on your site, a logical directory structure might be: <\/p>\n<pre>\/\n\/about\/\n\/blog\/\n\/contact\/\n<\/pre>\n<p>And if you had several blog entries inside your blog directory, your structure might grow like this:<\/p>\n<pre>\/\n\/about\/\n\/blog\/\n\/blog\/post-one\/\n\/blog\/post-two\/\n\/blog\/post-three\/\n\/contact\/\n<\/pre>\n<p>And therefore, a function could logically assume that anything inside the blog directory should be considered a part of the blog section of your site, and mark the blog link as active for those pages. This makes our job a lot easier. And luckily, most CMS platforms make this sort of directory structure pretty easy to create.<\/p>\n<p>The functions also assume that you have either a fairly shallow directory structure, or that you&#8217;re not linking to too many similarly nested directories. What I mean by this is, if you have this sort of a structure:<\/p>\n<pre>\/\n\/contact\/\n\/contact\/me\/\n\/contact\/me\/here\/\n<\/pre>\n<p>And you wanted to link to both \/contact\/ and \/contact\/me\/here\/ in your navigation bar, you might run into problems distinguishing between the two. There are ways to increase precision, but they come at the cost of flexibility. <\/p>\n<p>But enough of that. Let&#8217;s get to the good stuff!<\/p>\n<h3>A JavaScript Solution<\/h3>\n<p>I&#8217;ve written about this method before, when I previously talked about <a href=\"http:\/\/cssnewbie.com\/intelligent-navigation\/\">building intelligent navigation bars.<\/a> This technique is nice because it doesn&#8217;t rely on any JS frameworks, so you can add it to older sites without needing jQuery or the like. The basic function looks like this:<\/p>\n<pre lang=\"javascript\" escaped=\"true\" line=\"1\">function setActive() {\n  aObj = document.getElementById('nav').getElementsByTagName('a');\n  for(i=0;i&lt;aObj.length;i++) {\n    if(document.location.href.indexOf(aObj[i].href)&gt;=0) {\n      aObj[i].className='active';\n    }\n  }\n}<\/pre>\n<p>This function looks for an element with an id of &#8220;nav&#8221; (presumably your navigation bar), then looks at each of the anchor tags inside it. It then compares the anchor tag&#8217;s href tag with the page&#8217;s URL. If the href tag is contained within the URL anywhere, it gives that link a class of &#8220;active,&#8221; which I can then style specially in my CSS.<\/p>\n<p>As an example of what I mean by all that, if I had an anchor tag in my navigation bar that linked to &#8220;\/blog\/&#8221; and the page I was on was &#8220;\/blog\/this-is-a-post.html&#8221;, my blog link would be styled as active, because &#8220;\/blog\/&#8221; is contained within &#8220;\/blog\/this-is-a-post.html&#8221;.<\/p>\n<p>As a final note, you wouldn&#8217;t want to call this function until the page was finished loading: if you call it too soon, your links won&#8217;t exist yet! So you can either call it at the very end of your document, or dynamically call it when your page is done loading, with something like this:<\/p>\n<pre lang=\"javascript\" escaped=\"true\" line=\"1\">window.onload = setActive;<\/pre>\n<h3>A jQuery Solution<\/h3>\n<p>If you are already loading a framework like jQuery (like I do on almost every site I work on these days), this sort of functionality could be written even more succinctly. And like I said earlier, I&#8217;m a sucker for efficiency. Here&#8217;s a jQuery solution that does essentially the same thing in a much smaller space:<\/p>\n<pre lang=\"javascript\" escaped=\"true\" line=\"1\">$(document).ready(function() {\n\t$('#nav a[href^=\"\/' + location.pathname.split(\"\/\")[1] + '\"]').addClass('active');\n});<\/pre>\n<p>This function is making use of both native JavaScript and jQuery tricks to reach a whole new level of brevity. First, the whole thing is wrapped in a &#8220;document ready&#8221; function, which means it won&#8217;t fire until the page is loaded and our links are in place. Next, we&#8217;re looking for anchor tags inside our &#8220;nav&#8221; ID. And really, we&#8217;re looking for a very specific anchor tag: one whose href <strong>starts with<\/strong> (^=) a slash, followed by a part of our <strong>page&#8217;s location<\/strong> (location.pathname). Specifically, we&#8217;re looking for the first directory in our page&#8217;s URL.<\/p>\n<p>We&#8217;re doing this by making use of the JavaScript split() method, which lets us take any string (for example, &#8220;\/blog\/this-is-a-post.html&#8221;) and break it into an array based on a substring (in our case, the forward slash). If you&#8217;re familiar with PHP, it&#8217;s similar to the explode() function. In our example, we&#8217;d end up with a three-part array that looked like this: <\/p>\n<pre>[\"\",\"blog\",\"this-is-a-post.html\"]<\/pre>\n<p>Which means that if we look at the second value of our array (arrays start counting at zero, so [1] is the second value), that should give our first-level directory (&#8220;blog&#8221;, in our example). This lets us match any subsequent child directories with our parent in the navigation bar.<\/p>\n<h3>Tweaking for Home Links<\/h3>\n<p>Our jQuery function works great in most scenarios, but it fails if you have a &#8220;home&#8221; link where you&#8217;re just pointing to the root directory, like this:<\/p>\n<pre lang=\"html4strict\" escaped=\"true\" line=\"1\">&lt;a href=&quot;\/&quot;&gt;Home&lt;\/a&gt;<\/pre>\n<p>And because I tend to have a link like that, I needed a workaround. Here&#8217;s a way to get around that with just a little more code to account for our special case:<\/p>\n<pre lang=\"javascript\" escaped=\"true\" line=\"1\">$(document).ready(function() {\n\tif(location.pathname != \"\/\") {\n\t\t$('#nav a[href^=\"\/' + location.pathname.split(\"\/\")[1] + '\"]').addClass('active');\n\t} else $('#nav a:eq(0)').addClass('active');\n});<\/pre>\n<p>Here, we&#8217;re checking to see if we&#8217;re in the root directory. If so, we&#8217;re skipping the loop through our anchor tags and just making a specific anchor tag active. In this case, I&#8217;m giving the active class to the first anchor in our list (which is the most common location for a home link).<\/p>\n<p>And that&#8217;s that. If you know of even more efficient or fool-proof ways to accomplish this task, I&#8217;d love to hear about them in the comments section. Or if you&#8217;re skilled in a framework other than jQuery, feel free to share the equivalent code!<\/p>\n<p>Note: I apologize for the long gap between articles. I had some problems while rebuilding my PC (DOA motherboard) and was without my computer for several weeks.<\/p>\n<div class=\"wp-socializer wpsr-share-icons \" data-lg-action=\"show\" data-sm-action=\"show\" data-sm-width=\"768\" ><h3>Share and Enjoy !<\/h3><div class=\"wpsr-si-inner\"><div class=\"wpsr-counter wpsrc-sz-32px\" style=\"color:#000\"><span class=\"scount\"><span data-wpsrs=\"\" data-wpsrs-svcs=\"facebook,twitter,linkedin,pinterest,print,pdf\">0<\/span><\/span><small class=\"stext\">Shares<\/small><\/div><div class=\"socializer sr-popup sr-32px sr-circle sr-opacity sr-pad sr-count-1 sr-count-1\"><span class=\"sr-facebook\"><a rel=\"nofollow\" href=\"https:\/\/www.facebook.com\/share.php?u=\" target=\"_blank\"  title=\"Share this on Facebook\"  style=\"color: #ffffff\" ><i class=\"fab fa-facebook-f\"><\/i><span class=\"ctext\"><span data-wpsrs=\"\" data-wpsrs-svcs=\"facebook\">0<\/span><\/span><\/a><\/span>\n<span class=\"sr-twitter\"><a rel=\"nofollow\" href=\"https:\/\/twitter.com\/intent\/tweet?text=%20-%20%20\" target=\"_blank\"  title=\"Tweet this !\"  style=\"color: #ffffff\" ><i class=\"fab fa-twitter\"><\/i><\/a><\/span>\n<span class=\"sr-linkedin\"><a rel=\"nofollow\" href=\"https:\/\/www.linkedin.com\/sharing\/share-offsite\/?url=\" target=\"_blank\"  title=\"Add this to LinkedIn\"  style=\"color: #ffffff\" ><i class=\"fab fa-linkedin-in\"><\/i><\/a><\/span>\n<span class=\"sr-pinterest\"><a rel=\"nofollow\" href=\"https:\/\/www.pinterest.com\/pin\/create\/button\/?url=&amp;media=&amp;description=\" target=\"_blank\"  title=\"Submit this to Pinterest\"  style=\"color: #ffffff\" data-pin-custom=\"true\"><i class=\"fab fa-pinterest\"><\/i><span class=\"ctext\"><span data-wpsrs=\"\" data-wpsrs-svcs=\"pinterest\">0<\/span><\/span><\/a><\/span>\n<span class=\"sr-print\"><a rel=\"nofollow\" href=\"https:\/\/www.printfriendly.com\/print?url=\" target=\"_blank\"  title=\"Print this article \"  style=\"color: #ffffff\" ><i class=\"fa fa-print\"><\/i><\/a><\/span>\n<span class=\"sr-pdf\"><a rel=\"nofollow\" href=\"https:\/\/www.printfriendly.com\/print?url=\" target=\"_blank\"  title=\"Convert to PDF\"  style=\"color: #ffffff\" ><i class=\"fa fa-file-pdf\"><\/i><\/a><\/span><\/div><\/div><\/div>","protected":false},"excerpt":{"rendered":"<p>I&#8217;m all about efficiency when I&#8217;m writing web code, and navigation is often one of those areas where I try to improve my efficiency. Here are some ways to automatically style your &#8220;active&#8221; navigation elements using some streamlined JavaScript and\/or jQuery. [&#8230;]<\/p>\n<p><a class=\"more-link article\" href=\"https:\/\/cssdeck.com\/blog\/using-javascript-to-style-active-navigation-elements\/\" title=\"Click to read 'Using JavaScript to Style Active Navigation Elements'\">Read Article<\/a><\/p>\n","protected":false},"author":18,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":[],"categories":[165,184,188],"tags":[273,291,293,88],"_links":{"self":[{"href":"https:\/\/cssdeck.com\/blog\/wp-json\/wp\/v2\/posts\/424"}],"collection":[{"href":"https:\/\/cssdeck.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/cssdeck.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/cssdeck.com\/blog\/wp-json\/wp\/v2\/users\/18"}],"replies":[{"embeddable":true,"href":"https:\/\/cssdeck.com\/blog\/wp-json\/wp\/v2\/comments?post=424"}],"version-history":[{"count":0,"href":"https:\/\/cssdeck.com\/blog\/wp-json\/wp\/v2\/posts\/424\/revisions"}],"wp:attachment":[{"href":"https:\/\/cssdeck.com\/blog\/wp-json\/wp\/v2\/media?parent=424"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/cssdeck.com\/blog\/wp-json\/wp\/v2\/categories?post=424"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/cssdeck.com\/blog\/wp-json\/wp\/v2\/tags?post=424"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}