6.x menu.inc menu_tree_output($tree)
7.x menu.inc menu_tree_output($tree)

Returns an output structure for rendering a menu tree.

The menu item's LI element is given one of the following classes:

  • expanded: The menu item is showing its submenu.
  • collapsed: The menu item has a submenu which is not shown.
  • leaf: The menu item has no submenu.


$tree: A data structure representing the tree as returned from menu_tree_data.

Return value

A structured array to be rendered by drupal_render().

Related topics

4 calls to menu_tree_output()
book_block_view in modules/book/book.module
Implements hook_block_view().
book_children in modules/book/book.module
Formats the menu links for the child pages of the current page.
MenuTreeOutputTestCase::testMenuTreeData in modules/simpletest/tests/menu.test
Validate the generation of a proper menu tree output.
menu_tree in includes/menu.inc
Renders a menu tree based on the current path.


includes/menu.inc, line 1026
API for the Drupal menu system.


function menu_tree_output($tree) {
  $build = array();
  $items = array();

  // Pull out just the menu links we are going to render so that we
  // get an accurate count for the first/last classes.
  foreach ($tree as $data) {
    if ($data['link']['access'] && !$data['link']['hidden']) {
      $items[] = $data;
  $router_item = menu_get_item();
  $num_items = count($items);
  foreach ($items as $i => $data) {
    $class = array();
    if ($i == 0) {
      $class[] = 'first';
    if ($i == $num_items - 1) {
      $class[] = 'last';

    // Set a class for the <li>-tag. Since $data['below'] may contain local
    // tasks, only set 'expanded' class if the link also has children within
    // the current menu.
    if ($data['link']['has_children'] && $data['below']) {
      $class[] = 'expanded';
    elseif ($data['link']['has_children']) {
      $class[] = 'collapsed';
    else {
      $class[] = 'leaf';

    // Set a class if the link is in the active trail.
    if ($data['link']['in_active_trail']) {
      $class[] = 'active-trail';
      $data['link']['localized_options']['attributes']['class'][] = 'active-trail';

    // Normally, l() compares the href of every link with $_GET['q'] and sets
    // the active class accordingly. But local tasks do not appear in menu
    // trees, so if the current path is a local task, and this link is its
    // tab root, then we have to set the class manually.
    if ($data['link']['href'] == $router_item['tab_root_href'] && $data['link']['href'] != $_GET['q']) {
      $data['link']['localized_options']['attributes']['class'][] = 'active';

    // Allow menu-specific theme overrides.
    $element['#theme'] = 'menu_link__' . strtr($data['link']['menu_name'], '-', '_');
    $element['#attributes']['class'] = $class;
    $element['#title'] = $data['link']['title'];
    $element['#href'] = $data['link']['href'];
    $element['#localized_options'] = !empty($data['link']['localized_options']) ? $data['link']['localized_options'] : array();
    $element['#below'] = $data['below'] ? menu_tree_output($data['below']) : $data['below'];
    $element['#original_link'] = $data['link'];

    // Index using the link's unique mlid.
    $build[$data['link']['mlid']] = $element;
  if ($build) {

    // Make sure drupal_render() does not re-order the links.
    $build['#sorted'] = TRUE;

    // Add the theme wrapper for outer markup.
    // Allow menu-specific theme overrides.
    $build['#theme_wrappers'][] = 'menu_tree__' . strtr($data['link']['menu_name'], '-', '_');
  return $build;


Matt-H’s picture

The first line of the documentation for this function currently says, "Returns a rendered menu tree." This was true in previous versions, but in Drupal 7, the return is "a structured array to be rendered by drupal_render()." Therefore, the opening documentation should change as well.

sujoyit2005’s picture

Yes, the comment of "Matt-H on January 27, 2012 at 10:38pm" is TRUE. The function menu_tree_output($tree) does not, return a rendered html ul-li for menu, like when called as menu_tree_output(menu_tree_all_data('your-menu-name', null, $menu_depth));
Rather it return an structured array, that need to be passed through drupal_render() function to actually print the html. Please corrent the fist line of the documentation or give some scenario where the documentation is true.

Toraih’s picture

See below, over the comment-form:
> Buggy or inaccurate documentation? Please file an issue instead of commenting here.

Toraih’s picture

mobiro’s picture

I have created custom theme from html file and I need to render the main menu tree manually. So, I render the main menu tree in the page.tpl.php like this.

$menu_tree = menu_tree_all_data('main-menu');
$main_mn = menu_tree_output($menu_tree);
print render($main_mn);

But, it not working. the main menu doesn't rendered.
I try print_r($main_mn), Yes it displays all main menu array perfectly.

I know that code is fine. It works when I try in Zen sub-theme other drupal theme.
But, why is it not working in my custom theme? Have I miss something to initialize in my custom theme?

qqboy’s picture

i think
1, you can totally custom the theme output for the array by using hook theme, and theme_xxx or template_preprocess_THEMEHOOK.
2, consider if theme('item-list','items'=>data);