0

How can I theme all the menu levels individually in menu.html.twig?

I need to give different markup to the 2nd (child) and 3rd (grandchild) level, and in the twig I only have parent and child.

  {% if item.below %}
    {{ menus.menu_links(item.below, attributes.removeClass('nav'), menu_level + 1) }}
  {% endif %}

Whatever I put in this is duplicated for the child and grandchildren.

I thought that menu_level + 2 might get it. What does menu_level + do?


EDIT: Thanks to Hudri's tip below I did the following Thanks Hudri!

  {% if menu_level == 0 and item.is_expanded %}
    <li{{ item.attributes.addClass(item_classes) }}>
    <a href="{{ item.url }}" class="dropdown-toggle nav__title" data-target="" data-toggle="dropdown">{{ item.title }} </a>
  {% elseif menu_level == 1 %}
    <li{{ item.attributes.addClass(item_classes) }}>
    {{
      link(
        item.title,
        item.url,
        item.attributes.removeClass(item_classes),
        item.attributes.setAttribute('title', '')
      )
    }}
  {% elseif menu_level == 2 %}
    <li{{ item.attributes.addClass(item_classes) }}>
    {{
      link(
        item.title,
        item.url,
        item.attributes
      )
    }}

3 Answers 3

4

menu_links is a Twig macro, that is called recursively. That macro is located in menu.html.twig. In there you can do stuff based on current menu_level.

{% if menu_level == 0 %}
  <ul class="menu--main">
{% else %}
  <ul class="menu--sub">
{% endif %}

Notice that this macro is called recursivly, so if you are adding a classes like {% set attributes = attributes.addClass('menu--level' ~ menu_level) %}, this additional class is also stored and passed down recursivly!

Also take a look at core/themes/classy/templates/navigation/menu.html.twig to get an example of a full menu template file.

3
  • Thanks @Hudri! So there is no way to pick out different levels and apply specific theming?
    – petergus
    Commented Nov 15, 2018 at 7:41
  • You can do whatever you want, different for each level, but all has to be done in menu.html.twig - look at the example snippet I gave in the answer.
    – Hudri
    Commented Nov 15, 2018 at 7:44
  • 2
    Recursively means that the same template file is called multiple times. But each time the menu_level variables is set to a new value. React on that variable to create depth specific design.
    – Hudri
    Commented Nov 15, 2018 at 7:54
1

Use macro instead, that's better for recursive twig

1
  • Welcome to Drupal Answers. Can you expand this answer a little to show how a Twig macro can be used for this case?
    – mpdonadio
    Commented Oct 17, 2019 at 15:41
0

This is an example code of macro.

{% macro menu_links(items, attributes, menu_level) %}
  
  {% if items %}
    {% if menu_level == 0 %}
      <ul id="menu" class="menu">
    {% else %}
      <ul class="menu sub-nav">
    {% endif %}
    {% for item in items %}
      {%
        set classes = [
          'menu-item',
          item.is_expanded ? 'menu-item--expanded',
          item.is_collapsed ? 'menu-item--collapsed',
          item.in_active_trail ? 'menu-item--active-trail',
        ]
      %}
      <li{{ item.attributes.addClass(classes) }}>
        {{ link(item.title, item.url) }}
        {% if item.below %}
          {{ menus.menu_links(item.below, attributes, menu_level + 1) }}
        {% endif %}
      </li>
    {% endfor %}
    </ul>
  {% endif %}
{% endmacro %}```
    

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.