I want to generate the html elements and their classes to fit my styling of the main menu.

I'm confused by all the near-possibilities offered in the api documentation and by looking at core themes etc. and still can't quite see what I have to do, or where I have to do it.
I would be very grateful for clear pointers to:

  1. which php functions I have to write;
  2. which variables I need to add / update;
  3. in which files the functions will go.

Presumably, in MYTHEME.theme I will need a preprocess function of some sort to add to the attributes and item.attributes variables that links.html.twig uses to print the menu ul and the menu item li's.

[Update] So far I have discovered one way to place classes on the Main Menu's ul but ideally I would like to add a class to each submenu's ul indicating the depth of the sub-menu.
And I cannot locate any documentation or examples from which I can understand the generation / modifying of the main menu's individual link items.

This function goes into the file MYTHEME.theme.

function MYTHEME_preprocess_page(&$variables) {

  // Pass the main menu and secondary menu to the template as render arrays.
  if (!empty($variables['main_menu'])) {
    $variables['main_menu']['#attributes']['id'] = 'main-menu-links';
    $variables['main_menu']['#attributes']['class'] = array('links', 'clearfix', 'MYNEW_class');

  • You possibly want to wait for drupal.org/node/2256521 to land, that's a huge refactoring of the whole menu link system and it's likely that it will affect whatever you're currently doing.
    – Berdir
    Jul 11 '14 at 20:50
  • Thanks @Bedir. It looks like a mighty meaty refactoring! I'll keep the question open and aim to answer it when the new code hits an available alpha and I've had a chance to look at it.
    – iainH
    Jul 12 '14 at 15:43

Override the twig file for the main menu by saving menu--main.html.twig to your theme. Copy the original menu.html.twig from /core/modules/system/templates/menu.html.twig or /core/themes/classy/templates/navigation/menu.html.twig if your theme extends from Classy.

You can then modify the Twig macro used to generate the menu output. To get a class on the ul's to indicate level, you could do this:

{% if menu_level == 0 %}
  <ul{{ attributes.addClass('menu', 'menu-level--' ~ menu_level) }}>
{% else %}
  <ul class="menu {{ 'menu-level--' ~ menu_level }}">
{% endif %}

You could do similar manipulations to the li's:

<li{{ item.attributes }}>

Just tack on .addClass('class-name') to attributes like so:

<li{{ item.attributes.addClass('class-name') }}>

If you're a HTML/class name snob like myself you can also remove classes like so: {{ item.attributes.removeClass('menu-item') }}

Which I did on the line above the li in the for loop.

  • Nice answer @wesruv, I made some edits (pending) to try to answer the OP more directly on adding a class to indicate depth. Thanks!
    – Cottser
    Jun 22 '15 at 15:01
  • Thanks Cottser, I feel like I barely deserve credit for the much improved answer :)
    – wesruv
    Aug 11 '15 at 19:21

The way to get the main menu with items in all levels has been resolved in Drupal 8 - "Implement menu links as plugins", trying to build a menu tree

To add class to ul and li, we got 3 options:

A. Override menuTree service:

  1. create new MenulinkTree in your module MyprojectMenuLinkTree that extends core's MenuLinkTree
  2. Override MenulinkTree::build by adding MyprojectMenuLinkTree::build
  3. Update your level specifi class in logic like this https://gist.github.com/vijaycs85/308d2d0287a9ab1cd168
  4. ovrride defult menu.link_tree at sites/default/services.yml https://gist.github.com/vijaycs85/1179c6009c6932405f10

P.S: Not very sure, if you need to do these whole override for adding class.

B. Override just tree build on theme layer:

  1. Add the code in mytheme.theme file: https://gist.github.com/vijaycs85/61f2b2757f83aaa5260e

C. Using Drupal.behaviors.MYTHEME in JavaScript (from https://www.drupal.org/project/gratis)

  1. Create MYTHEME/script.js
  2. Add MYTHEME.behaviour.menuTree
  3. Update this code: https://gist.github.com/vijaycs85/346c14aedffcafe8945e
  • Thanks @vijaycs85. Since my question is essentially about theming, I think either of your options B and C will be sufficient for what I want. We temporarily abandoned our D8 project and until we eventually get back to it, it looks like you have provided the answer.
    – iainH
    Aug 23 '14 at 4:33
  • (I took this opportunity to re-read all 155 posts in drupal.org/node/2256521 to regain some confidence in continuing to invest in D8!)
    – iainH
    Aug 23 '14 at 4:40

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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