How to create multilevel dropdown menu in hugo?

Hey Guys,
Can anyone please tell how can we create a multilevel dropdown menu in hugo and how we are going to assign weights?

Hi, see the sidebar template example of this documentation article.

Essentially you can do this:

{{ range .Site.Menus.main }}
    {{ if .HasChildren }}
        <li class="{{ if $currentPage.HasMenuCurrent "main" . }}active{{ end }}">
                <span>{{ .Name }}</span>
            <ul class="sub-menu">
            {{ range .Children }}
            ...
        </li>
     ...

Then you can define menu weights and hierarchy in page front matter like this.

Other variant would be to navigate sections directly:

{{ range site.Sections }}
  li class={{ if .IsAncestor $ }}active{{ end }}
    a href={{ .RelPermalink }} {{ .Title }}
    ul
      {{ range .Sections }}
        / ...
      {{ end }}
{{ end }}

In that case you would assign weight within the section index page front matter.

The dropdown part you can do with CSS and / or javascript - this is not strictly dependent on Hugo

2 Likes

can u show the example if i share u my file

    {{ range .Site.Menus.main }} {{ if .HasChildren }}
  • {{ .Name }}
  • {{ else }}
  • 							<a href="{{ .URL }}" >{{ .Name }}</a>
        								{{ end  }}
                                </li>
                                    {{ end }}
                               </ul>
    

    This is my code and this is how i am callinfg menu from config file
    [[menu.main]]
    identifier = “parent”
    name = “Who We Are”
    url = “/who-we-are/”
    weight = “1”

    [[menu.main]]
    identifier = “what-we-do”
    name = “What We Do”
    url = “/what-we-do/”
    weight = “2”

    [[menu.main]]
    parent = “what-we-do”
    name = “Projects”
    identifier = “projects”
    url = “/projects/”
    weight = “1”

    [[menu.main]]
    parent =“projects”
    name = “Experiences”
    url = “/events/”
    weight = “1”

Did you check the sidebar example in the documentation? It should work pretty much out of the box. There is one caveat - if you want the “active” classes to work, you will need to define menu entries in page front matter (see second link I posted) instead of config.toml.

Here’s a complete example with recursive nesting:

{{ define "menu-item" }}
  {{ $page := .page }}
  {{ with .entry }}
    {{ if .HasChildren }}
      <li class="{{ if $page.HasMenuCurrent "main" . }}active{{ end }}">
        <a href="{{ .URL }}">{{ .Name }}</a>
        <ul class="sub-menu">
          {{ range .Children }}
            {{ template "menu-item" (dict "entry" . "page" $page) }}
          {{ end }}
        </ul>
      </li>
    {{ else }}
      <li class="{{ if $page.IsMenuCurrent "main" . }}active{{ end }}">
        <a href="{{ .URL }}">{{ .Name }}</a>
      </li>
    {{ end }}
  {{ end }}
{{ end }}

<ul>
  {{ $page := . }}
  {{ range .Site.Menus.main }}
    {{ template "menu-item" (dict "entry" . "page" $page) }}
  {{ end }}
</ul>

After a lot of fiddling I got a drop-down menu defined in config.toml working. The help files are a bit unclear on how to do it, and I found no help here.

Here is how I have done it. It’s a drop-down menu for my tags, here are two of them. The weight controls the order in which they appear in the drop-down menu.

[[menu.main]]
name = “History” # Drop-down menu entry
url = “/tags/history/”
weight = 4
parent = “Tags” # Entry in main menu

[[menu.main]]
name = “Hiking” # Menu entry in dropdown menu
url = “/tags/hiking/”
weight = 5
parent = “Tags” # Entry in main menu

You need to do three things to generate multilevel dropdown menu in Hugo:

1. Add menu and submenu configuration in config.toml file

...
[menu]
  [[menu.main]]
    identifier = "category"
    name = "Category"
    url = "/category"
    weight = 1
  [[menu.main]]
    identifier = "category1"
    name = "Category1"
    url = "/category/1"
    parent = "category"
    weight = 1
  [[menu.main]]
    identifier = "category2"
    name = "Category2"
    url = "/category/2"
    parent = "category"
    weight = 2
  [[menu.main]]
    identifier = "category3"
    name = "Category3"
    url = "/category/3"
    parent = "category"
    weight = 3

You should understand each field under [[menu.main]]:

  • identifier should be unique name of menu within the menu structure. It is used to identify menu, submenu and their relation by hugo internally.
  • name should be the name which you want to display on the menu item.
  • url is a relative URL which will be opened when you click on the menu item.
  • weight is for sequencing the menu items. Menu items with less weight appear first in the menu. Same is applicable for submenu, submenu items with less weight appear first in the dropdown.
  • parent is used in submenu item only to tell who is the parent of the submenu. You use the identifier of the parent menu in this field.

2. Create a partial menu.html to generate HTML from the configuration

{{ range .Site.Menus.main }}
    {{ if .HasChildren }}
        <li class="{{ if $currentPage.HasMenuCurrent "main" . }}active{{ end }}">
                <span>{{ .Name }}</span>
            <ul class="sub-menu">
            {{ range .Children }}
            ...
        </li>
     ...

Things to note in the above partial is use of {{- if .HasChildren }} condition to check if menu has submenu children or not. If it is having submenu children, then we loop them through using {{ range .Children }}

3. Apply CSS for menu and submenu

This is the most important part to apply responsive CSS so that it works for both desktop and mobile.

I used Hugo to generate my blog website and added support for the nested menu structure. I have written an article for all the changes I have done on my Hugo website to support the nested menu.

1 Like

Here is a link for multimenu dropdown that I’ve been using in my projects. Everything is done with CSS and there are animations used