3

When I output the main menu this is the html that gets generated:

<ul id="main-menu" class="links inline clearfix">
    <li class="menu-218 first active"><a href="/drupal/" class="active">Home</a></li>
    <li class="menu-294"><a href="/drupal/node/2">Page</a></li>
    <li class="menu-293 last"><a href="/drupal/node/1">page</a></li>
</ul>

However I'd like to completely restructure the menu like this:

<nav id="main-nav" class="animate">
            <div class="grid__wrapper">
                <div class="grid t--np nrp">
                    <a class="button animate" href="#" title="Sign up">SIGN UP</a>
                    <a class="button animate" href="#" title="Login">LOGIN</a>
                    <a class="main-nav__button animate grid__item xl--1-5 l--1-5 sp s--tbp t--tbp" href="<?php echo $front_page; ?>">HOME</a>
                    <a class="main-nav__button animate grid__item xl--1-5 l--1-5 sp s--tbp t--tbp" href="#">LINK 1</a>
                    <a class="main-nav__button animate grid__item xl--1-5 l--1-5 sp s--tbp t--tbp" href="#">LINK 2</a>
                    <a class="main-nav__button animate grid__item xl--1-5 l--1-5 sp s--tbp t--tbp" href="#">LINK 3</a>
                    <a class="main-nav__button animate grid__item xl--1-5 l--1-5 sp s--tbp t--tbp" href="#">LINK 4</a>
                </div>
            </div>
        </nav>

How can I change the html output of the menu as well as the links inside?

Ideally I'd like to output any menus as a element and be able to pass classes and an id to each one, the same also goes for the links inside.

Also the first two links in the menu are login and signup buttons which only display at certain screen sizes and have completely different classes to the rest of the menu links. Is this also possible to do?

I have tried altering the theme_menu_tree and theme_menu_link functions but am having no luck as I am somewhat of a beginner in PHP and Drupal.

3 Answers 3

4

Most likely that your theme renders them menu either in theme_preprocess_page() in its template.php and passing it page.tpl.php. That's how Garland does it:

https://api.drupal.org/api/drupal/themes%21garland%21template.php/function/garland_preprocess_page/7

https://api.drupal.org/api/drupal/includes%21theme.inc/function/theme_links/7

Given your question, you're most likely going to end up with a custom theme, which is normal for most sites. The best way to tackle this is to change the logic in preprocess_page to set it up how you like.

That's more sustainable and specific than altering or overriding theme_links() globally in module-space.

2

Instead of trying to alter the html of the main menu the theme prints out for you, it could be easier to disable the main menu from the theme settings and use the Menu block module for rendering the menu, and Menu attributes module to add some additional attributes such as ids, classes, styles etc. to menu items. Those extra links, sign up and login, you can create at menu configuration itself at admin/structure/menu/manage/main-menu/add.

This way ýou can have high quality html with all the necessary ids and classes you'll ever need for making the main menu look what you want. You can also assign the menu block to any region you want.

https://drupal.org/project/menu_block

https://drupal.org/project/menu_attributes

1
  • I think this is the better method. Messing about with template.php and hacking the way menus render is just horrible, and something I've done countless times on Drupal sites. It's just more effort than it's worth, and using contrib modules that render the menu in their own way is much more flexible and easy to use. +1 Jul 31, 2015 at 9:27
0

Although I'm sure the answers posted are both great solutions I couldn't manage to get to grips with either. My solution was to create a custom links__system_main_menu function for my theme like this:

function mytheme_links__system_main_menu($variables) {
$site_frontpage = variable_get('site_frontpage', 'node');
  $html = "<nav id='main-nav' class='animate'>\n";
  foreach ($variables['links'] as $link) {
      if($link['href'] == '<front>') {
        $html .= "<a class='main-nav__button animate grid__item xl--1-5 l--1-5 sp s--tbp t--tbp' href='" .$site_frontpage ."'>" .$link['title'] ."</a>";
      }
      else {
        $html .= "<a class='main-nav__button animate grid__item xl--1-5 l--1-5 sp s--tbp t--tbp' href='" .$link['href'] ."'>" .$link['title'] ."</a>";
      }
  }
  $html .= "</nav>\n";

  return $html;
}

The separate rule for the front page link was due to receiving <front> in the href of the a tag normally.

One thing I couldn't do however was pass classes through to the function. from here in my page template:

print theme('links__system_main_menu', array('links' => $main_menu, 'heading' => t('Main menu')));

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

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