I need this structure to my drupal main-menu:

<div class="list-group">
  <a href="#" class="list-group-item active">
    Cras justo odio
  <a href="#" class="list-group-item">Dapibus ac facilisis in</a>
  <a href="#" class="list-group-item">Morbi leo risus</a>
  <a href="#" class="list-group-item">Porta ac consectetur ac</a>
  <a href="#" class="list-group-item">Vestibulum at eros</a>

Im use bootstrap theme, and menu_block module.

this is my template.php file, I need to remove the li tags.


 * @file
 * template.php

function bootstrap_subtheme_menu_tree__menu_block__main_menu($variables){
    //add class for ul
    return '<div class="list-group">' . $variables['tree'] . '</div>';
function bootstrap_subtheme_menu_link__menu_block__main_menu($variables){
    //add class for li
    //$variables['element']['#attributes']['class'][] = '';
    //add class for a
    $variables['element']['#localized_options']['attributes']['class'][] = 'list-group-item';
    return theme_menu_link($variables);

2. With Menupoly (advanced users)

An alternative solution is to use Menupoly with a MenuTheme implementation that will render links without the ul/li. You can think of this like a formatter for menus.

When and why?

Typically, the basic theme overrides as in the other answer are sufficient.
But there are some use cases where Menupoly can be preferable:

  • You want to reuse the theme html in another project, or for another menu.
  • You want to render the same menu more than one place, with different HTML. E.g. in the header you want only links + separator, but in the sidebar you want the usual ul + li. In this case, the targeted theme override won't cut it.

Solution 1: Menupoly as a block

Create a custom module.

Optionally, create a custom MenuTheme implementation, similar to this one. Or just use the existing one.

If you create your own, make sure that the class can be found with an autoloader, or put it in a file that is always included.

Then, implement hook_menupoly() to define a menu block:

function MYMODULE_menupoly() {
  return array(
    'topnav_flat' => array(
      'menu_name' => 'main-menu',
      'depth' => 1,
      'menu_theme' => new menupoly_MenuTheme_FlatLinksWithSeparator(' | '),

Solution 2: Without a block.

To skip the part with the block, you can directly do this in your theme.

Implement THEMENAME_preprocess_page(), and add this:

function THEMENAME_preprocess_page(&$vars) {
  $settings = array(
    'expand' => MENUPOLY_EXPAND_ALL,
    'menu_name' => 'user-menu',
    ... // more options possible
  $html = menupoly_view($settings);
  $vars['topnav_flat'] = menupoly_view($settings);

Then, in your page.tpl.php:

<?php print $topnav_flat; ?>
  • Thank you very much for your answer, but I would like to resolve it with theme overrides, so it's like I've been doing all my projects. thanks – Marco.M Mar 17 '14 at 16:52
  • 1
    This is fine. But the idea is that these questions and answers should be useful to other people, too.. – donquixote Mar 17 '14 at 17:36

1. Using theme overrides.

You can override theme_menu_link() and theme_menu_tree() in your theme.

However, you probably only want to target this one menu and not every other menu. To achieve this, you can use targeted overrides for theme_menu_link() and theme_menu_tree():


Or (as you figured out yourself) there are specific overrides for menu_block:



function THEMENAME_menu_tree__menu_block__MENU_NAME($variables){
    //add class for ul
    return '<div class="list-group">' . $variables['tree'] . '</div>';

function THEMENAME_menu_link__menu_block__MENU_NAME(array $variables) {
  $element = $variables['element'];
  // Omit all the submenu stuff, since this will only be used to display the top level.
    $sub_menu = '';

    if ($element['#below']) {
      $sub_menu = drupal_render($element['#below']);
  $link_options = $element['#localized_options'];
  $link_options['attributes']['class'][] = 'list-group-item';
  return l($element['#title'], $element['#href'], $link_options);
  • I am not a developer, I'm a designer learning to develop, thanks for the reply, but I need more help – Marco.M Mar 17 '14 at 15:40
  • 1
    Ok, but there is a limit to how much can be done in a stackexchange answer. I assume you are using a custom theme that is a sub-theme of bootstrap? – donquixote Mar 17 '14 at 15:51
  • 1
    "return theme_menu_link($variables);" this does not help, instead you should copy and modify the contents of theme_menu_link(). – donquixote Mar 17 '14 at 16:15
  • I use a sub-theme of bootstrap and menu_block module. I need to rewrite the markup of the menu show with the module menu_block – Marco.M Mar 17 '14 at 17:03
  • Answer modified. – donquixote Mar 17 '14 at 18:06

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