Create a mega menu with Drupal 8

a old boat

Creating a responsive mega menu is often a regular prerequisite on any project, Drupal 8 or other. And if we can find some solutions offering to create mega menus easily, very often these solutions remain quite rigid and can hardly be adapted to the prerequisites of a project. But what is a mega menu? It is nothing more than a menu that contains a little more than a list of links (proposed by the menu system of Drupal 8), with specific links, text, images, call to actions, etc.

Rather than a rigid solution, which may be appropriate if we are willing to meet its requirements, we can also use a more flexible, open solution that also requires a little more work at the theming level. Let's find out how to build a mega menu with the Simple Mega Menu module.

General overview

The main idea of ​​this module is based on two assumptions:

  • A mega menu can be designed using all the power of the Field API of Drupal 8, in fact in the same way that we construct different content type by adding different field types to them.
  • The final rendering is delegated to the Twig template engine, leaving a large margin of maneuver for positioning the different elements of a mega menu.

Simple mega menu is therefore not a solution out of the box that will provide you with a mega menu immediately usable (whatever it offers an example of mega menu pre-configured if one activates the example module). It simply allows to use a content entity as support for its mega menu, and thus to be able to use any type of field; Including links, references to content, images, videos, text, embedded widgets, views, and more. In short, everything you can do with the Drupal 8 content entity types.

For rendering the mega menu, the module provides two Twig functions:

  • has_megamenu (item.url): lets you know if a menu link has a mega menu attached to it
  • view_megamenu (item.url, view_mode): allows to display the mega menu in the specified display mode

With these two Twig functions, you can then display a mega menu in any ways, formatted from the twig template of the mega menu entity, to the exact place where you want to position your mega menu in relation to the menu link (and its possible children).

Let's find out more about how Simple Mega Menu works.

Creating a mega menu type

Once the module is installed, we need to create a mega menu type available in the Administration > Structure menu, at the URL /admin/structure/simple_mega_menu_type.

Add mega menu type

 

We create a mega menu entity type and we select for which menus the contents of this type of mega menu will be available.

 

Create mega menu type

 

Once the mega menu type saved we can then manage, like any content entity type, the different fields that will compose it, its view modes, form modes, etc. 

 

Add fields to mega menu

 

Here we have added some fields

  • Links: a multiple Link field
  • Image: an image field
  • Text: a long text field
  • Bottom links: another link multiple field

 

Add fields to mega menu

 

We then configure the different view modes of our entity. By default, the module installs two view modes, Before and After. You can of course delete them, or add as many as you want.

Here we configure the Image and Text fields to be displayed in the Before view mode.

Mega menu view mode before configuration

 

And the After view mode is configured to display only links from the Link field.

Mega menu view mode after configuration

 

To add and configure other display modes, simply go to the configuration url (/admin/structure/display-modes/view) and add a new one.

Mega menu add new view mode

To stay simple in this tutorial, we will not add the Bottom view mode, which we should configure to allow us to display only the Bottom Links field. But I think you have understood the principle.

After these few configuration operations, strictly similar to the management of content types, we have a mega menu type that will allow us to create our contents and associate these contents with elements of the targeted menu(s) selected previously.

You should also remember to set permissions to allow visitors or users of your site to view mega entities published or not.

 

Mega menu configuration permissions

 

Creating the mega menu contents

We can access from the menu Contents > Simple mega menu list to the list of mega menus entities created.

 

Liste des mega menus

 

And of course we can create as many as necessary using the appropriate button.

 

Création d'un élément de mega menu

 

And our first content of our mega menu is created.

Premier élément du mega menu

 

Linking mega menu items to menu links

To display our first mega menu content, we must select it from the menu link for which we want to display this mega menu. To do this, a new field is available in the menu link form. Select (autocompletion field) the previously created mega menu from the Simple Mega menu field.

 

Association mega menu to menu link

 

And here it is finished, or almost. You can repeat as many as necessary on the different links of your menu this operation. Also make sure that your menu block is configured correctly to display a sufficient menu depth.

 

Menu bloc configuration

 

By default, with the Twig template provided by the module, the mega menu attached to links will only be displayed if this link has child links. So make sure you have some child links on your main menu link.

 

Menu hierarchy

 

If you do not have or do not want child links, just do it, just modify the default Twig template by copying it to your theme, and edit a few lines according to yours needs.

Customizing the mega menu with Twig

The Simple Mega Menu module provides a default template for menus, for menus that are targeted by a mega menu type. This template is just a simple override of the default Twig template included with Drupal 8, on which a few lines have been added. These few lines will allow you to inject each part of your mega menu to a very precise place of your menu HTML structure.

Let's discover this template

 

{% 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
#}
{{ attach_library('simple_megamenu/base') }}
{{ menus.menu_links(items, attributes, 0) }}

{% macro menu_links(items, attributes, menu_level) %}
  {% import _self as menus %}
  {% if items %}
    {% if menu_level == 0 %}
      <ul{{ attributes.addClass('menu', 'menu--simple-mega-menu') }}>
    {% else %}
      <ul {{ attributes.removeClass('menu--simple-mega-menu') }}>
    {% 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 %}
          {% if has_megamenu(item.url) %}
            <div class="mega-menu-wrapper">
              <div class="mega-menu-background"></div>
              {{ view_megamenu(item.url, 'before') }}
              {{ menus.menu_links(item.below, attributes.addClass('mega-menu-item'), menu_level + 1) }}
              {{ view_megamenu(item.url, 'after') }}
            </div>
          {% else %}
            {{ menus.menu_links(item.below, attributes.removeClass('mega-menu-item'), menu_level + 1) }}
          {% endif %}
        {% endif %}
      </li>
    {% endfor %}
    </ul>
  {% endif %}
{% endmacro %}

 

The most significant part of this template is of course where the mega menu is rendered.

<li{{ item.attributes.addClass(classes) }}>
  {{ link(item.title, item.url) }}
  {% if item.below %}
    {% if has_megamenu(item.url) %}
      <div class="mega-menu-wrapper">
        <div class="mega-menu-background"></div>
        {{ view_megamenu(item.url, 'before') }}
        {{ menus.menu_links(item.below, attributes.addClass('mega-menu-item'), menu_level + 1) }}
        {{ view_megamenu(item.url, 'after') }}
      </div>
    {% else %}
      {{ menus.menu_links(item.below, attributes.removeClass('mega-menu-item'), menu_level + 1) }}
    {% endif %}
  {% endif %}
</li>

 

Using the has_megamenu() function, we can test whether the link has a mega menu attached to it, using the view_mega_menu() function we can display our mega menu in any view mode. And we have complete freedom to position our mega menu according to our needs.

For example your main menu links do not have children links but just a mega menu. Modify this portion of code as well and the case is set.

<li{{ item.attributes.addClass(classes) }}>
  {{ link(item.title, item.url) }}
  {% if has_megamenu(item.url) %}
    <div class="mega-menu-wrapper">
      <div class="mega-menu-background"></div>
      {{ view_megamenu(item.url, 'before') }}
      {{ view_megamenu(item.url, 'after') }}
    </div>
  {%endif %}
  {% if item.below %}
    {{ menus.menu_links(item.below, attributes, menu_level + 1) }}
  {% endif %}
</li>

 

You need a specific class for your main links containing a mega menu? Just add an extra class.

{%
  set classes = [
    'menu-item',
    item.is_expanded ? 'menu-item--expanded',
    item.is_collapsed ? 'menu-item--collapsed',
    item.in_active_trail ? 'menu-item--active-trail',
    has_megamenu(item.url) ? menu-item--megamenu,
  ]
%}

etc. etc.

Mega menus within range of Twig

This module does not offer a packaged solution within click range, just within range of Twig. But personally I think I have never been able to use such a solution, as the constraints are often multiple. And since the solution provided by this module is limited to just doing the necessary, namely to insert particular HTML markup within a list of classic menu links, this one remains compatible with any other module intervening on the menu system, modules that can offer you, for example, an amazing responsive menu such as those provided by the module Responsive and off-canvas menu.

This module allows us to offer a graphical interface to editors to update easily elements of a mega menu, relying mainly on the Drupal 8 core and its entities, while allowing a Drupal developer (or a developper front end knowing Twig) to precisely position these different elements, and to be able to get in a few hours a mega menu completely mastered. The rest, formatting of the mega menu in particular, is no longer a matter of Magic CSS. And it's not necessarily the easiest part.

 

Commentaires

Soumis par (or a develop… (non vérifié) le 08/06/2017 à 11:16 - Permalien

l interface to editors to update easily elements of a mega menu, relying mainly on the Drupal 8 core and its entities, while allowing a Drupal developer (or a developper front end knowing Twig) to precisely position these different elements, and to be able to get in a few hours a mega menu completely mastered. The rest, formatting of the mega menu in particular, is no longer a matter of Magic CSS. And it's not necessarily the easiest part.

Soumis par Thomas (non vérifié) le 17/10/2017 à 16:19 - Permalien

Great job! Thank you so much. Finaly a usefull, maximum flexible megamenu solution in Drupal.

Ajouter un commentaire