I've fetched the main menu for the website using the code below.

public function build() {
    $menu_name = 'main';
    $menu_tree = \Drupal::menuTree();
    $parameters = $menu_tree->getCurrentRouteMenuTreeParameters($menu_name);
    $tree = $menu_tree->load($menu_name, $parameters);
    $manipulators = array(
      array('callable' => 'menu.default_tree_manipulators:checkAccess'),
      array('callable' => 'menu.default_tree_manipulators:generateIndexAndSort'),
    $tree = $menu_tree->transform($tree, $manipulators);
    $build['menu'] = $menu_tree->build($tree);

return array(
      '#theme' => 'allofus_menu_footer',
      '#build' => $build,

I'm trying to put it as a block, but I want to show it as a 2 coloumn. In the first coloumn, first main menu and its sub menus and the rest of main and sub menus in the second coloumn.

I've created a twig but it does not print anything except markup. I've tried to foreach but it is not working.


{% if build %}
    <nav id ="secondary-menu" class="navigation" role="navigation">
        {{ build }}
{% endif %}

1 Answer 1


I just did a lot of this with Menu Block. I prefer Menu Block as it is a little more flexible and offers more template suggestions and hooks than the core menu module. It kind of looks like you are building your own block above, I can't tell, but you can save time by using Menu Block in that case.

In one of my menus, this is the twig file that handles the output. I did not do any preprocess or extra stuff, just built around the macro concept used in menu.html.twig. Every parent item has children, and if those children items exceed 7, it will start a new list. For example, if the menu link has 14 children, then my code will have a drop down consisting of 2 unordered lists with 7 links each. Our style then makes them into columns. This is a little different from your use case, but should get you on the right track.

 * @file
 * Theme override to display a menu.
 * Available variables:
 * - menu_name: The machine name of the menu.
 * - items: A nested list of menu items. Each menu item contains:
 *   - attributes: HTML attributes for the menu item.
 *   - below: The menu item child items.
 *   - title: The menu link title.
 *   - url: The menu link url, instance of \Drupal\Core\Url
 *   - localized_options: Menu link localized options.
 *   - is_expanded: TRUE if the link has visible children within the current
 *     menu tree.
 *   - is_collapsed: TRUE if the link has children within the current menu tree
 *     that are not currently visible.
 *   - in_active_trail: TRUE if the link is in the active trail.
{% import _self as menus %}

  We call a macro which calls itself to render the full tree.
  @see http://twig.sensiolabs.org/doc/tags/macro.html
{{ menus.menu_links(items, attributes, 0) }}

{% macro menu_links(items, attributes, menu_level) %}
  {% import _self as menus %}
  {% if items %}
      {% for item in items %}
          set classes = [
            item.in_active_trail ? 'active-trail',
            item.below ? 'has-submenu'

        <li{{ item.attributes.addClass(classes) }}>
          {{ link(item.title, item.url) }}
          {% if item.below %}
            {{ menus.submenu_links(item.below, attributes, menu_level + 1) }}
          {% endif %}
      {% endfor %}
  {% endif %}
{% endmacro %}

{% macro submenu_links(items, attributes, menu_level) %}
  {% import _self as menus %}
  <div class="global-top__submenu">
    {% for chunk in items|batch(7) %}
      <ul class="global-top__submenu-col">
        {% for item in chunk %}
          <li{{ item.attributes }}>
            {{ link(item.title, item.url) }}
        {% endfor %}
    {% endfor %}
{% endmacro %}
  • This does not make menus in 2 coloumns bro Commented Dec 23, 2016 at 11:18
  • It does if you use markup and style to do it, which is what the chunk | batch line is doing. The style is making them into columns. The batch creates a new ul list every 7 items. If my menu had 21 children, there would be 3 columns in our drop down.
    – Kevin
    Commented Jul 15, 2017 at 19:23

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.