As you know default wrapper for menu item in Drupal 7 can be modified via function theme_menu_link().

by overriding

theme_menu_link($variables) {} 

function we can modify the rendered html output of menu link but it will change all of menu items that their #theme attribute is set to this function. for example in main menu, each item has menu_link__main_menu value in it's #theme attribute.

Now I want to create a custom wrapper function in my theme.

I searched and I found I must create a function with structure like

theme_menu_link($variables) {}

and also I must REGISTER the function name in my theme.

For registration, I used function theme_theme() {}

function theme_theme() {return array('custom_menu_item_wrapper' => array());}

** theme is replaced by name of theme ** custom_menu_item_wrapper is the name of my function for wrapping operation

But I don't know, how should I define parameters in theme function registration because when custom_menu_item_wrapper($variables) function is called $variables is NULL

2 Answers 2


Indeed, you need to register a new theme implementation. Looking about the specification of the hook_theme(), each information array must contain either a variables element or a render element. This is missing in your case and causes the empty $variables argument.

function YOURTHEME_theme()
    // define a custom theme implementation
    return array(
        'menu_link_custom' => array(
            'render element' => 'element',

function YOURTHEME_menu_link_custom($variables)
    //Build and return custom HTML for your link
  • I do appreciate for your guidance. 'render element' => 'element' is my key :) Thanks a lot Mike.
    – Mehrdad201
    Commented Jan 4, 2014 at 15:43
  • Dear Mike, I have an important question, can you tell me how did you know that we must write 'render element' => 'element', in array ? is there any guidance for it ?
    – Mehrdad201
    Commented Jan 10, 2014 at 19:27
  • The API docs of Drupal writes that either a render element or variables should be defined in your theme definition in order to work correctly. About the choice of element value for the render element is based on Drupal guidelines ... but you can use your own logic if you want. This only defines the name of the variable passed the theme function. In this case, it would be $variables['element']. Commented Jan 11, 2014 at 10:13

You should not have to register any themes. It is already registered and being used if you have the menu module enabled, which I will assume you do.
All you need to do is override the theme_menu_link by putting a function in the template.php file. You can just paste the current one (which I will post below), Change the 'theme' part in the function name to match your theme name, then edit as necessary.

Default theme_menu_link:

function theme_menu_link(array $variables) {
  $element = $variables['element'];
  $sub_menu = '';

  if ($element['#below']) {
    $sub_menu = drupal_render($element['#below']);
  $output = l($element['#title'], $element['#href'], $element['#localized_options']);
  return '<li' . drupal_attributes($element['#attributes']) . '>' . $output . $sub_menu . "</li>\n";
  • I know this hook, but as I said in my post, if I use this function overriding, It will affect all menu links. I need to create custom wrapper with custom function. Indeed I want to change value of #theme attribute to set custom wrapper function name.
    – Mehrdad201
    Commented Jan 4, 2014 at 7:48
  • Indeed I want to create additional menu item wrapper function and then I want to change #theme attribute of some of my tree menu items (directly by changing modifying array values) . So when Drupal render is called. all menu items are wrapped via it's defined menu wrapper function and therefore my specific menu items are wrapped via custom wrapper and the others are wrapped via default wrapper.
    – Mehrdad201
    Commented Jan 4, 2014 at 8:31
  • Can you not just check which menu is going through the function by checking the variables and then alter the output depending on said menu? It seems to me it would be much easier.
    – 2pha
    Commented Jan 5, 2014 at 0:58

Your Answer

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

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