Alex Selimov


Highlighting the active menu item in Hugo

Published: Jul 03, 2023

I’ve recently been developing sites for some family/friends. I had one person request highlighting the currently selected menu item. I had built a custom theme which used a navbear defined in the site wide hugo.toml. There were a few different solutions but I wanted to highlight the solution I ended up using for my use case. A dummy of my site directory set up is:

content
    |-- section1
            |--_index.md
            |--section1Post.md
    |-- section2
            |--_index.md
            |--section2Post.md
    |-- section3
            |--_index.md

In my header partial I created a menu by looping over the entries in [[menu.main]] defined in the hugo.toml. It’s important here to end the url with a /. Hugo adds an ending /, to the urls of the pages that it creates. While this might not be necessary to make the hyperlink work, it will be necessary to get the highlighting correct. The definition of the menu looks like:

[menu]
  [[menu.main]]
    name= "section1"
    url= "/section1/"
    weight= "1"
  [[menu.main]]
    name= "section2"
    url= "/section2/"
    weight= "2"
  [[menu.main]]
    name= "section3"
    url= "/section3/"
    weight= "3"

The original header partial is pretty simple. I just loop over the range .Site.Menus.main and insert a <div class="item"> which is my div class for a navbar menu item. I populate the text and link from the variables associated with the main menu item. This is all wrapped within a <nav> element with other items and stylings that create the overall navigation menu. The loop for insertion of menu items is below:

{{ range .Site.Menus.main }} 
    <div class="item">
            <a href="{{ .URL }}">
                {{ $text := print .Name | safeHTML }}
                {{ $text }}
            </a>
        </div>
{{ end }}

As I mentioned before, there were a few different solutions but the one I went with was to save the menu item url and the current page url into two separate variables. I can then compare these to determine whether the current page corresponds to a menu item and if so I change the class of the div from a normal menu item to the activated menu item class. This concept can be seen in action in the following code snippet:

{{ $currentPage := . }}
{{ range .Site.Menus.main }} 
    {{ $menu_item_url := .URL | relLangURL }}
    {{ $page_url:= $currentPage.RelPermalink | relLangURL }}
    <div 
         {{ if eq $menu_item_url $page_url }}
            class="active-item"
    {{else}}
            class="item"
    {{ end }}
    >
            <a href="{{ .URL }}">
                {{ $text := print .Name | safeHTML }}
                {{ $text }}
            </a>
        </div>
{{ end }}

I hope that this is helpful to somebody else as it took me a decent amount of time to try the different recommended methods before I found this one. As always shoot me an email if you have any thoughts or comments!