Make menu.html.twig easier to understand

Created on 11 July 2016, almost 9 years ago
Updated 11 April 2025, 16 days ago

The menu_links macro in menu.html.twig wraps its {% for item in items %} in a {% if items %} to prevent the opening and closing ul from outputing. That's a standard PHP pattern. But it is NOT a standard Twig pattern. Twig has a special loop variable that is built specifically for cases like this, the loop variable. http://twig.sensiolabs.org/doc/tags/for.html#the-loop-variable

Currently we do this:

  {% if items %}
    {% if menu_level == 0 %}
      <ul{{ attributes.addClass('menu') }}>
    {% else %}
      <ul class="menu">
    {% endif %}
    {% for item in items %}
      <li>…
    {% endfor %}
    </ul>
  {% endif %}

But we should use Twig's loop variable like this instead:

  {% for item in items %}
    {% if loop.first %}
      {% if menu_level == 0 %}
        <ul{{ attributes.addClass('menu') }}>
      {% else %}
        <ul class="menu">
      {% endif %}
    {% endif %}
    <li>…
    {% if loop.last %}
      </ul>
    {% endif %}
  {% endfor %}

Additionally, our if-ul-else-ul-endif construct means we have 2 opening ul tags and 1 closing ul tags. This causes a Twig analysis "error" in IDEs like PhpStorm:

Element ul is not closed

So this is even better:

  {% for item in items %}
    {% if loop.first %}
      <ul
        {% if menu_level == 0 %}
          {{ attributes.addClass('menu') }}
        {% else %}
          class="menu"
        {% endif %}
      >
    {% endif %}
    <li>…
    {% if loop.last %}
      </ul>
    {% endif %}
  {% endfor %}
πŸ› Bug report
Status

Active

Version

11.0 πŸ”₯

Component

theme system

Created by

πŸ‡ΉπŸ‡ΌTaiwan johnalbin Taipei, Taiwan

Live updates comments and jobs are added and updated live.
Sign in to follow issues

Comments & Activities

Not all content is available!

It's likely this issue predates Contrib.social: some issue and comment data are missing.

  • πŸ‡ΊπŸ‡ΈUnited States mortona2k Seattle

    The macro can be replaced with an SDC.

    menu.html.twig would include system:menu component, which can include itself and pass item.below as items, just like the macro is doing.

    Themers can set up different menu components for main/secondary/sidebar styles.

Production build 0.71.5 2024