Search code examples
javascriptjqueryjekyllliquid

how to add class 'active' to nav item whose href is in the location.pathname


I'm trying to build on top of a Jekyll template to build a blog style site. I'm currently in the process of writing and styling the navigation, which is giving me a couple of problems. Using the answer to this question I've managed to add the class active on the current page, but here are the issues that still need ironing out:

  • First, all the 'tabs' are active when the page loads, not just the 'home' tab:

Project homepage screenshot

  • Second, the relevant 'tab' is no longer active when the url goes deeper than the first level of navigation. The url of the below screenshot is [baseurl]/reviews/[name-of-post], but the reviews 'tab' is not active:

enter image description here

I'm not sure how to approach the first problem, but for the second I think I will need to search the location.pathname for the relevant href, but I need to look further into this. Will update as necessary, but I've been playing around with this for ages with no luck so thought I'd post in the meantime.

Below are the code snippets for the relevant parts:

Side navigation HTML (written in Liquid)

<nav id="side-nav">
  <ul class="nav-items-list">
    <li id="nav-item"><a href="{{ site.baseurl }}/"><i class="fas fa-home"></i></a></li>
    {% for page in site.pages %}
    <li id="nav-item">
      <a href="{{ site.baseurl }}/{{ page.title | downcase }}/">
      <i class="{{ page.icon }}"></i>
      </a>
    </li>
    {% endfor %}
  </ul>
</nav>

Example page (YAML frontmatter)

---
layout: page
title: Reviews
permalink: /reviews/
icon: "fas fa-star-half-alt"
---

jQuery

$(function(){
  var current = location.pathname;
  $('#nav-item a').each(function(){
      var $this = $(this);
      if($this.attr('href').indexOf(current) !== -1){
          $this.addClass('active');
      }
  })
})

That should hopefully be enough, but if any more code is needed, please let me know. All the code is also available on GitHub, where the project is also hosted on GitHub Pages.

Thanks in advance.

Jamie


Solution

  • The following should theoretically work:

    // Compute the closest (2-part) base path from the current location
    var basePath = '/' + window.location.pathname.split('/', 3).filter(Boolean).join('/') + '/';
    
    // Add `active` class to the corresponding link if any
    $('#nav-item a[href="' + basePath + '"]').addClass('active');
    

    The first line basically takes the first 2 parts of the pathName, so:

    • if the URL is /glossd/, it yields /glossd/,
    • if the URL is /glossd/reviews/, it yields /glossd/reviews/,
    • if the URL is /glossd/reviews/something/, it still yields /glossd/reviews/.