I have had problems with getting the 'current menu item' to highlight in Hugo for as long as I've been using it (at least two years).
It appears possible if I define the menu using the frontmatter in my content files (i.e., individually adding each piece of a content to a menu). However, I don't want to litter the frontmatter of my content files with this information, especially seeing as how it is possible to define your menus using the main config file.
Here is how I declare my menu in my config file (I prefer to use JSON instead of YAML):
"menu": {
"main": [
{
"name": "Home",
"weight": 1,
"url": "/"
},
{
"name": "About",
"weight": 2,
"url": "/about"
},
{
"name": "Blog",
"weight": 3,
"url": "/blog"
},
{
"name": "Contact",
"weight": 4,
"url": "/contact"
}
]
},
And here is my menu template
<ul class="nav">
{{ $currentPage := . }}
{{ range .Site.Menus.main }}
{{ if .HasChildren }}
<li class="nav-item nav-item--has-submenu{{ if $currentPage.HasMenuCurrent " main" . }} nav-item--active{{ end }}">
<a class="nav-link" href="javascript:;" title="{{ .Name }}">
{{ .Pre }}
<span>{{ .Name }}</span>
</a>
<ul class="nav-submenu">
{{ range .Children }}
<li class="nav-item{{ if $currentPage.IsMenuCurrent " main" . }} nav-item--active{{ end }}">
<a class="nav-link" href="{{ .URL }}" title="{{ .Name }}">
<span>{{ .Name }}</span>
</a>
</li>
{{ end }}
</ul>
</li>
{{else}}
<li class="nav-item">
<a class="nav-link" href="{{ .URL }}" title="{{ .Name }}">
{{ .Pre }}
<span>{{ .Name }}</span>
</a>
</li>
{{end}}
{{end}}
</ul>
I know that the markup above is specifically checking the frontmatter of each piece of content, and I understand why it isn't working. All I would like to know is what changes I must make in order to highlight the current menu item.
I think defining menus via the config file is for adding non-Hugo links to a menu and thus, there is no need to highlight those items. Is this even possible, or am I going to have to accept that I need to use the frontmatter within my content in order to build my menus?
Thanks
I see two issues, either of which could cause problems.
The first issue, and the one I think is causing your trouble, is that you aren't ending your URLs with a slash. Hugo normalizes all URLs to end in a slash, and will redirect to the correct URL, but when .IsMenuCurrent
and .HasMenuCurrent
compare URLs to see if they refer to the same resource, they don't take this into account; they only see that /blog
and /blog/
are different.
Try using:
"menu": {
"main": [
{
"name": "Home",
"weight": 1,
"url": "/"
},
{
"name": "About",
"weight": 2,
"url": "/about/"
},
{
"name": "Blog",
"weight": 3,
"url": "/blog/"
},
{
"name": "Contact",
"weight": 4,
"url": "/contact/"
}
]
},
The second issue is that the .IsMenuCurrent
and .HasMenuCurrent
methods don't take into account that you may be running a multilingual site, in which a single standard URL like /blog/
from your menu config may be rewritten /en/blog/
or /es/blog/
via relLangURL
in order to correctly link to the appropriate page for the current language. So, if you are trying to keep your menu config DRY, you will probably find that those two methods only work for (at most) your primary language.
This doesn't seem to apply to you, based on the template you provided, but I'll include the solution for others who find this question.
In order to fix this you either need to maintain separate menus for each language, which is a pain, or use your own logic to determine if the menu entry points to the current page. Fortunately, it's pretty straightforward:
{{ $currentPage := . }}
{{ range .Site.Menus.main }}
{{ $menu_item_url := .URL | relLangURL }}
{{ $page_url:= $currentPage.RelPermalink | relLangURL }}
{{ if eq $menu_item_url $page_url }}
{{/* the menu item links to the current page (with relLangURL) */}}
{{ end }}
{{ end }}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With