Drupal - Render menu in twig template

Simplify Menu sounds like what you'd want.

The simplify_menu module uses a TwigExtension to gain access to Drupal's main menu's (or any other menu for that matter), render array so it can be accessed from a twig template. Among the many advantages of having full control of the menu's render array in a twig template is the ability to customize the markup for your menus to ensure they are accessible and comply with standards.

// Get menu items
{% set items = simplify_menu('main') %}

// Iterate menu tree
<ul>
  {% for menu_item in items.menu_tree %}
    <li class="{{ item_class }} navigation__item">
      <a href="{{ menu_item.url }}" class="{{ link_class }}">{{ menu_item.text }}</a>
    </li>
  {% endfor %}
</ul>

Otherwise, there are a handful of menu-* twig templates to use when rendering a menu from a block. Turn on your Twig debugging settings in Drupal to see what the suggestions are.

However, you need to have pretty good knowledge of menu theming to get it exactly right (like handling child items and not flat menu structure as the example above displays) - that said, I would stick to letting a block render out the menu in a given region. Then, inspect menu.html.twig from your base theme (either classy or stable) to get an idea of what your options are if you want to modify markup.

Be sure to use a decent twig template suggestion and not just menu.html.twig - as that will affect every menu that gets rendered by Drupal... it is the default template.

I would also suggest to install Menu Block as that will grant extra flexibility in theming and twig file suggestions. It also makes rendering trees of a menu (like section based navigation in a sidebar) a breeze.


Enable the simplify_menu module, then add the code below to your page.html.twig or other twig template where you would like to render your menu:

<nav class="navigation__main" role="navigation">
  {% set item_class = 'navigation__item' %}
  {% set link_class = 'navigation__link' %}
  <ul class="navigation__items">
    {% set items = simplify_menu('main') %}
      {% for menu_item in items.menu_tree %}
          <li class="{{ item_class }}"><a href="{{ menu_item.url }}" class="{{ link_class }}">{{ menu_item.text }}</a></li>
      {% endfor %}
  </ul>
</nav>

the 'main' is the menu id which you can find by hovering over the menu's edit button in the menus page and looking at the url displayed at the bottom of the browser.


For those who are still looking for an alternative approach, I suggest using Twig Tweak module as a more stable and more global use case, check out its cheat sheet

For rendering the menu via twig tweak, you can just do the following:

{# Expand menu items to display the entire menu tree. #}    
{{ drupal_menu('menu_machine_name') }}

{# Specify menu level and depth. #}
{{ drupal_menu('admin', 2, 3) }}