Skip to main content
Eystein codes

Highlighting the current category in Eleventy

How to mark the navigation item as active from a sub-page under the active menu item. That's a mouthfull, but that's as simple as I can put it.

Site architecture #

For this website I have the following hierarchy:

_site/
├─ home
├─ about
├─ posts/
│  ├─ index
│  ├─ post 1
│  ├─ post 2
├─ portfolio/
│  ├─ index
│  ├─ work 1
│  ├─ work 2

Original navigation code #

Note: This markup is based on v5 of the 11ty-base-blog. The current (v8) uses an aria attribute instead of a class. It smells like an accessibility error if I was to set aria-current="page" on the parent, so I'm sticking with using a class for this example.

The default code for the navigation in the 11ty-base-blog is as following. This is in Nunjucks (.njk) markup:


<ul class="nav">
  {%- for nav in collections.nav -%}
    <li class="nav-item
      {% if nav.url == page.url %} nav-item-active{% endif %}
    ">
      <a href="{{ nav.url | url }}">{{ nav.data.navtitle }}</a>
    </li>
  {%- endfor -%}
</ul>

When the two are the same, that link is the page we are currently on.

(Be aware that the /posts/ folder is what I refer to as the "Blog". Sorry.)

This works well on the home, about and index pages, which when rendered to HTML looks like this:

<ul class="nav">
  <li class="nav-item"><a href="/">Home</a></li>
  <li class="nav-item"><a href="/about/">About me</a></li>
  <li class="nav-item nav-item-active"><a href="/posts/">Blog</a></li>
  <li class="nav-item"><a href="/hire-me/">Hire me</a></li>
  <li class="nav-item"><a href="/portfolio/">Portfolio</a></li>
</ul>

The class nav-item-active is displayed on the "Blog" link, because this is on the blog index page.

The issue #

The problem arrises when I click into any of the posts listed on the blog index page. Let's say I'm reading this blogpost, the URL will be https://eystein.no/posts/show-active-parent-nav/.

In this case the nav.url value is show-active-parent-nav, and thus there are no items to hightlight as active:

<ul class="nav">
  <li class="nav-item"><a href="/">Home</a></li>
  <li class="nav-item"><a href="/about/">About me</a></li>
  <li class="nav-item"><a href="/posts/">Blog</a></li>
  <li class="nav-item"><a href="/hire-me/">Hire me</a></li>
  <li class="nav-item"><a href="/portfolio/">Portfolio</a></li>
</ul>

So we need to check if show-active-parent-nav has portfolio as a parent.

Check if the current page is a child of Portfolio (or Blog). #

The way I solved this was by checking if the words "posts" or "portfolio" are part of the page URL, and also part of the navigation URL.

We can do that by using the Nunjucks if ( "something" in this.object) condition.

This is the finished filter, using or and and to add additional conditions to the filters.


<ul class="nav">
  {%- for nav in collections.nav -%}
    <li class="nav-item
      {%
        if ('/portfolio/' in nav.url ) and ('/portfolio/' in page.url)
			  or ('/posts/' in nav.url ) and ('/posts/' in page.url)
			  or (nav.url == page.url)
      %}
		    nav-item-active
	    {% endif %}
    ">
      <a href="{{ nav.url | url }}">{{ nav.data.navtitle }}</a>
    </li>
  {%- endfor -%}
</ul>