I would like to add an active class when:
I am on a page
I am on a category page
To the category item in the menu when the post/page in that category is open
My menu is in this format in config.toml
[menu]
[[menu.main]]
identifier = "Name"
name = "Name"
url = "/category/name/"
weight = number
And my navigation is like this
<ul class="nav-menu">
{{ $currentPage := . }}
{{ range .Site.Menus.main }}
<li class="{{ if $currentPage.HasMenuCurrent "main" . }}active{{ end }}">
<a href="{{.URL}}">{{ .Name }}</a></li>
{{ else }}
<li><a href="{{.URL}}">{{ .Name }}</a></li>
{{ end }}
</ul>
What am I missing?
esawertu:
What am I missing?
Two things.
1) Use .IsMenuCurrent
instead of .HasMenuCurrent
.
2) In your site configuration, use pageref
instead of url
(known issue ).
[[menu.main]]
name = "Foo"
pageref = "/category/foo/"
[[menu.main]]
name = "Bar"
pageref = "/category/bar/"
[[menu.main]]
name = "Baz"
pageref = "/category/baz/"
2 Likes
Thanks! So, this is how it has worked so far:
On a page - it is not working when I define a different [menu][menu-nav]
and assign page links to it. The workaround was to add the menu: nav
weight: number
to the front matter of every page I wanted in the (footer) navigation and they appeared automatically in the navigation without configuring them in config.toml
.
On a category page - works by retaining the code in the config.toml
and adding IsMenuCurrent
as you suggested.
Highlighting category as active in main navigation when a post is opened - does not work. Adding the frontmatter menu: main
makes the post title appear in the navigation. That would mean over 250 entries in the title alone.
I would prefer to define the pages in the config so I can shorten the titles and have the “highlight category when post open” issue work too.
zwbetz
November 30, 2021, 12:49pm
4
Like @jmooring mentioned there seems to be better ways to handle this now-a-days.
But in the past, @esawertu I’ve handled it like this:
{{ $current := . }}
{{ range site.Menus.nav }}
{{ $active := or ($current.IsMenuCurrent "nav" .) ($current.HasMenuCurrent "nav" .) }}
{{ $active = or $active (eq .Name $current.Title) }}
{{ $active = or $active (eq .URL $current.RelPermalink) }}
{{ $active = or $active (and (eq .Name "Blog") (eq $current.Section "blog")) }}
<a class="{{ if $active }}active{{ end }}" href="{{ .URL }}">
{{ .Name }}
</a>
{{ end }}
1 Like
@zwbetz that is causing all manors of issues.
zwbetz
November 30, 2021, 1:55pm
6
You’ll have to tweak it for your setup.
So at the least change
site.Menus.nav
To be
site.Menus.main
Nav should show the footer menu, but your code made the menu appear on the top navigation as well. I am using .page.path
in Jekyll to get option 3 to work, but I am not sure what Hugo’s equivalent is.
See also https://stackoverflow.com/a/56454338/5155484 for multi lang websites
<div class="collapse navbar-collapse" id="navbarNav">
<ul class="navbar-nav">
{{ $currentPage := . }}
{{ range site.Menus.main }}
{{ $menu_item_url := .URL | relLangURL }}
{{ $page_url := $currentPage.RelPermalink | relLangURL }}
{{ $active := eq $menu_item_url $page_url }}
<li class="nav-item">
<a class="nav-link{{ if $active }} active{{ end }}"
href="{{ $menu_item_url }}"
{{ if $active }}aria-current="page"{{ end }}>{{ .Name }}</a>
</li>
{{ end }}
</ul>
</div>
tyco
May 4, 2025, 12:55pm
9
Just do it the Hugo way. See Menus . Plus Hugo has had rapid development in 7 years, and a rule of thumb is to always give precedence to the docs.
{{ with site.Menus.main }}
<nav class="menu">
{{ range . }}
{{ if $.IsMenuCurrent .Menu . }}
<a class="active" aria-current="page" href="{{ .URL }}">{{ .Name }}</a>
{{ else }}
<a href="{{ .URL }}">{{ .Name }}</a>
{{ end }}
{{ end }}
</nav>
{{ end }}
2 Likes
Thank you, here is my updated version:
<div class="collapse navbar-collapse" id="navbarNav">
{{ with site.Menus.main }}
<ul class="navbar-nav">
{{ range . }}
{{ $active := $.IsMenuCurrent .Menu . }}
<li class="nav-item">
<a class="nav-link{{ if $active }} active{{ end }}"
href="{{ .URL }}"
{{ if $active }}aria-current="page"{{ end }}>{{ .Name }}</a>
</li>
{{ end }}
</ul>
{{ end }}
</div>