Community Documentation

Nice Menus horizontal children

Last updated November 30, 2008. Created by kasiawaka on April 18, 2008.
Edited by add1sun. Log in to edit this page.

I use Nice Menus (thank you for that module!) and wanted to use 'down' option but with the 2nd level (and next) displayed horizontally. The current code allows the first level to be horizontal but every next one is displayed in vertical position.
To achieve that I modified css and also added 'downdown' options to the module code. Changes to the nice_menus.module file (step 2 of 2) are not necessary since the css code can simply replace, for example, css code for 'down' . (in that case, replace downdown with down in the step 1 of 2)

I used nice_menus_default.css file (from modules/nice_menus/) to create my own nice_menus.css http://drupal.org/node/185543 and placed it in themes/zen/ folder (where zen is my current theme).
After that, I modified that nice_menus.css file as well as added extra option downdown to modules/nice_menus/nice_menus.module file.

The code is probably not perfect and I didn't test it using the administration part, I simply added code

  $menu = theme('nice_menu', 1, 77, 'downdown');  
  print $menu['content'];

to the template where I wanted the menu to be displayed. In my case 77 is the menu id - to find your menu id, check Administer -> Menus -> hover over the Edit link under your menu name. You will see the path like http://.../?q=admin/build/menu/menu/edit/77 where the the last number is your menu id.

Step 1 of 2

Changes to nice_menu.css - add this code:

/******************************
HORIZONTAL (downdown) menus
******************************/

ul.nice-menu-downdown {
  width: 65.5em; /* width of the 2nd level menu horizontal line - if you have more items in the menu, you may need to change this value so they all fit in one horizontal line*/
}

ul.nice-menu-downdown li {
  width: 12.5em;
}

ul.nice-menu-downdown ul {
  width: 65.5em;  /* width of the 2nd level menu horizontal line - if you have more items in the menu, you may need to change this value so they all fit in one horizontal line*/
  left: 5em; /* change if you want the 2nd level menu to be shifted to the right/left */
}

ul.nice-menu-downdown ul ul {
  width: 65.5em;  /* width of the 3rd level menu horizontal line - if you have more items in the menu, you may need to change this value so they all fit in one horizontal line*/
  left: 5em; /* change if you want the 3rd level menu to be shifted to the right/left */
  top: 1.8em; /* height of the 2st menu level and also margin after which 3rd level starts */
}

ul.nice-menu-downdown li.menuparent,
ul.nice-menu-downdown li li.menuparent {
  background: #eee url(arrow-down.png) right center no-repeat;
}

ul.nice-menu-downdown li.menuparent:hover,
ul.nice-menu-downdown li.over,
ul.nice-menu-downdown li li.menuparent:hover,
ul.nice-menu-downdown li li.over {
  background: #ccc url(arrow-down.png) right center no-repeat;
}

Step 2 of 2

Changes to nice_menus.module (located in modules/nice_menus/)
Replace

      $form['nice_menus_type_'. $delta] = array(
        '#type' => 'select',
        '#title' => t('Menu Style'),
        '#description' => t('right: menu items are listed on top of each other and expand to the right') .'<br />'. t('left: menu items are listed on top of each other and expand to the left') .'<br />'. t('down: menu items are listed side by side and expand down'),
        '#default_value' => variable_get('nice_menus_type_'. $delta, 'right'),
        '#options' => drupal_map_assoc(array('right', 'left', 'down')),
      );
      return $form;

with the code
      $form['nice_menus_type_'. $delta] = array(
        '#type' => 'select',
        '#title' => t('Menu Style'),
        '#description' => t('right: menu items are listed on top of each other and expand to the right') .'<br />'. t('left: menu items are listed on top of each other and expand to the left') .'<br />'. t('down: menu items are listed side by side and expand down').'<br />'. t('downdown: menu items are listed side by side on all levels'),
        '#default_value' => variable_get('nice_menus_type_'. $delta, 'right'),
        '#options' => drupal_map_assoc(array('right', 'left', 'down', 'downdown')),
      );
      return $form;

Comments

Hey men I did exactly all

Hey men I did exactly all your steps and didnt work.

I believe that problem is that i dont know exactly where do I paste this

$menu = theme('nice_menu', 1, 77, 'downdown');
print $menu['content'];

I pasted in the top of mi code in page.tpl. Am I OK?

I dont know a lot of php, but I apreciate your help.

CSS is incomplete

It wouldn't work with me either. It appears that there is nothing in the CSS to tell the lists to display horizontally!

EDIT: Here is the CSS that I used.

/******************************
HORIZONTAL (downdown) menus
******************************/

ul.nice-menu-downdown {
  width: 800px; /* width of the 1st level menu horizontal line */
  float: left;
}

ul.nice-menu-downdown li {
  width: 100px;
  display: block;
  text-align: left;
}

ul.nice-menu-downdown ul {
  width: 800px;  /* width of the 2nd level menu horizontal line */
  left: 0em; /* change if you want the 2nd level menu to be shifted to the right/left */
}

ul.nice-menu-downdown ul  li {
  width: 100px;  /* width of each 2nd level list item */
}

ul.nice-menu-downdown ul ul {
  width: 800px;  /* width of the 3rd level menu horizontal line */
  left: 0em; /* change if you want the 3rd level menu to be shifted to the right/left */
  top: 1.8em; /* height of the 2st menu level and also margin after which 3rd level starts */
}

ul.nice-menu-downdown ul  ul li {
  width: 100px;  /* width of each 3rd level list item */
}


ul.nice-menu-downdown li.menuparent,
ul.nice-menu-downdown li li.menuparent {
  background: #eee url(arrow-down.png) right center no-repeat;
}

ul.nice-menu-downdown li.menuparent:hover,
ul.nice-menu-downdown li.over,
ul.nice-menu-downdown li li.menuparent:hover,
ul.nice-menu-downdown li li.over {
  background: #ccc url(arrow-down.png) right center no-repeat;
}

Some notes on my CSS:
- I changed "65.5em" to "800px" as the former size was much too large for my menu. Your mileage may vary.

- I had to add extra li tags for each level, because they aren't inherited on some browsers.

- Because of the way the HTML is written (embedded lists), all sub-layers will line up to the left side of its parent, not to the left side of the menu system itself. In order to fix that, you would need to set the sub-layers to position: fixed; and position them according to the parent window. (This would need to be done independently for each level, or else they'd be rendered on top of each other.)

- You will almost certainly want to change the background colors.

- If you don't mind losing the default horizontal menu system, you can always just put these styles in the nice-menu-down class instead. This eliminates having to hack the nice_menus.module file.

Hopefully this helps!

-Karlheinz

Addendum

The line-up-to-left-of-parent issue has been bugging people for a while now, both here and in the issues tracker.

I found the way to fix it. In the nice_menus.css file (the one you're not supposed to edit), there's this bit of CSS:

ul.nice-menu li {
   position: relative;
}

This must be OVERRIDDEN for horizontal menus to work:

/* override nice_menus.css */
ul.nice-menu-down li {
   position: static;
}

This doesn't apply to my code above, but if you are copying/modifying the CSS from the nice-menu-down class, you also need to change the "clear" attribute on the child menu's list items. So, change:

ul.nice-menu-down ul li {
  clear: both;
}

...to:

ul.nice-menu-down ul li {
  clear: none;
}

And away you go!

EDIT: There's one other issue I should mention. Make sure you explicitly set the width of child menus. If you don't, then it's possible the child menu won't be "stickied."

Say you have a parent item at the right side of the menu. You roll your mouse over it and its child menu appears, floated left as you would expect. But if the child menu isn't long enough, it won't overlap the parent item, so you'll need to move the mouse off of the parent menu item, hiding the child menu before you can click on anything.

All the CSS on this page sets the child menus' widths, so this is only an issue if you're rolling your own CSS.

-Karlheinz

easy primary links

For those of you concerned about just printing out your primary links...

I used this:

print theme('nice_menu_primary_links','downdown');

instead of this:

$menu = theme('nice_menu', 1, 77, 'downdown'); 
print $menu['content'];

That way you don't have to find your menu id.

This still works-- Thank you!

This still works-- Thank you! You saved my project :)

Worked great!

Thanks!
I put the menu in a block, instead of hard-coding it in the template. There I have easier menu id control, and role control - I serve up different menus for different roles. I removed the fixed width declarations, so the buttons flex with the size of the contents. Is there some browser compatibility reason to have fixed width, or was that just a choice?

at karlheinz

Thanx! Great tips.

nobody click here