We have created two menu blocks: main_menu (region=main nav) and main_menu_footer (region=footer) that are added to all pages. They both are displaying the same main navigation menu except main_menu_footer only displays the first level and main_menu displays all levels.

I have a custom module, mymodule that I am using to assign a custom twig template, menu--main.html.twig. This twig template is being assigned to both blocks.

How can I setup the twig templates so that the main_menu uses main--menu.html.twig template, but main_menu_footer uses main--menu--footer.html.twig?


  1. main_menu block uses main--menu.html.twig template
  2. main_menu_footer block uses main--menu--footer.html.twig template

Current setup

function mymodule_theme($existing, $type, $theme, $path) {
  $items = [];
  $items['main__menu'] = [
    'base hook' => 'menu',
    'render element' => 'menu',

  return $items;
  • 2
    You need to add theme name suggestions, but this can be tricky in this case to distinguish both menus, see drupal.stackexchange.com/questions/193610/…
    – 4uk4
    Sep 12, 2018 at 18:57
  • One other thing, always start with the base hook when naming template hooks, so in this case $items['menu__main'].
    – 4uk4
    Sep 12, 2018 at 19:00
  • @4k4 the link you shared helped me resolve my issue. i pasted the answer for reference. Sep 12, 2018 at 23:31

2 Answers 2


This is usually done at the theme level, not the in a module. Unless you want to create your own implementation of a menu.
First of all, enable Twig Debugging then in locate in DOM the templates you want to override.
In your active theme, create a file with the same name as the twig template you want to override. Copy the code from the original template and customize it as you like

  • Yes, this is about the theming level, but you can use theming hooks in both, themes and modules.
    – 4uk4
    Sep 12, 2018 at 19:05

Using @4k4 suggestion, I got it resolved by doing the following

 * Implements hook_preprocess_block().
function mymodule_preprocess_block(&$variables) {
  // Only proceed if id is valid. It is not valid for all blocks. 
  if(isset($variables['attributes']['id'])) {
    $variables['content']['#attributes']['block'] = $variables['attributes']['id'];

 * Implements hook_theme_suggestions_HOOK_alter().
function mymodule_theme_suggestions_menu_alter(array &$suggestions, array $variables) {
  // Remove the block and replace dashes with underscores in the block ID to
  // use for the hook name.
  if (isset($variables['attributes']['block'])) {
    $hook = str_replace(array('block-', '-'), array('', '_'),    $variables['attributes']['block']);
    $suggestions[] = $variables['theme_hook_original'] . '__' . $hook;

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.