7.x theme.inc theme_link($variables)

Returns HTML for a link.

All Drupal code that outputs a link should call the l() function. That function performs some initial preprocessing, and then, if necessary, calls theme('link') for rendering the anchor tag.

To optimize performance for sites that don't need custom theming of links, the l() function includes an inline copy of this function, and uses that copy if none of the enabled modules or the active theme implement any preprocess or process functions or override this theme implementation.


array $variables: An associative array containing the keys:

  • text: The text of the link.
  • path: The internal path or external URL being linked to. It is used as the $path parameter of the url() function.
  • options: (optional) An array that defaults to empty, but can contain:
    • attributes: Can contain optional attributes:

      • class: must be declared in an array. Example: 'class' => array('class_name1','class_name2').
      • title: must be a string. Example: 'title' => 'Example title'
      • Others are more flexible as long as they work with drupal_attributes($variables['options']['attributes]).
    • html: Boolean flag that tells whether text contains HTML or plain text. If set to TRUE, the text value will not be sanitized so the calling function must ensure that it already contains safe HTML.

The elements $variables['options']['attributes'] and $variables['options']['html'] are used in this function similarly to the way that $options['attributes'] and $options['html'] are used in l(). The link itself is built by the url() function, which takes $variables['path'] and $variables['options'] as arguments.

See also



Related topics

1 string reference to 'theme_link'
l in includes/common.inc
Formats an internal or external URL link as an HTML anchor tag.
1 theme call to theme_link()
l in includes/common.inc
Formats an internal or external URL link as an HTML anchor tag.


includes/theme.inc, line 1738
The theme system, which controls the output of Drupal.


function theme_link($variables) {
  return '<a href="' . check_plain(url($variables['path'], $variables['options'])) . '"' . drupal_attributes($variables['options']['attributes']) . '>' . ($variables['options']['html'] ? $variables['text'] : check_plain($variables['text'])) . '</a>';


charlietoleary’s picture

Note: A link render array requires the HTML option, even though it is optional in the l() function

$link = array(
  '#theme' => 'link',
  '#text' => 'Click Here',
  '#path' => $path,
  '#options' => array(
    'attributes' => array('class' => array('cool-class'), 'id' => 'cool-id'),
      'html' => FALSE,
sonictruth’s picture

This smells buggy to me. If the 'attributes' array has elements in it then 'html' doesn't have to exist. But if 'attributes' is an empty array then Drupal will complain when there is not 'html' element set. Seems odd that '#options' aren't optional.

milesw’s picture

When I use pound signs in the array keys I get fatal errors. It works without the pound signs though...

dalin’s picture

Perhaps the other comments here relate to an older version of the function, but the current way to use this in a render array is something like:

    $img = array(
      '#theme' => 'image_style',
      '#style_name' => 'avatar_80x80',
      '#path' => $uri,
    $render = array(
      '#theme' => 'link',
      '#text' => drupal_render($img),
      '#path' => "node/" . $node->nid,
      '#options' => array(
        'attributes' => array(),
        'html' => TRUE,

Remember to set html to FALSE if #text is not already sanitized.

effulgentsia’s picture

rolkos’s picture

How to display description on menus in Drupal 7:

Just copy paste this code to template.php in your theme dir and rename MYTHEME_links. Remember to remove ending '?>'

function MYTHEME_links($variables) {
  $links = $variables['links'];
  $attributes = $variables['attributes'];
  $heading = $variables['heading'];
  global $language_url;
  $output = '';

  if (count($links) > 0) {
    $output = '';

    // Treat the heading first if it is present to prepend it to the
    // list of links.
    if (!empty($heading)) {
      if (is_string($heading)) {
        // Prepare the array that will be used when the passed heading
        // is a string.
        $heading = array(
          'text' => $heading,
          // Set the default level of the heading.
          'level' => 'h2',
      $output .= '<' . $heading['level'];
      if (!empty($heading['class'])) {
        $output .= drupal_attributes(array('class' => $heading['class']));
      $output .= '>' . check_plain($heading['text']) . '</' . $heading['level'] . '>';

    $output .= '<ul' . drupal_attributes($attributes) . '>';

    $num_links = count($links);
    $i = 1;

    foreach ($links as $key => $link) {
      $class = array($key);

      // Add first, last and active classes to the list of links to help out themers.
      if ($i == 1) {
        $class[] = 'first';
      if ($i == $num_links) {
        $class[] = 'last';
      if (isset($link['href']) && ($link['href'] == $_GET['q'] || ($link['href'] == '<front>' && drupal_is_front_page()))
          && (empty($link['language']) || $link['language']->language == $language_url->language)) {
        $class[] = 'active';
      $output .= '<li' . drupal_attributes(array('class' => $class)) . '>';

      if (isset($link['href'])) {
        // Pass in $link as $options, they share the same keys.
// $attributes['id'] - menu name change it from 'main-menu' to your menu name if you like to display description in some other menu
		if(isset($attributes['id'])&& $attributes['id']=='main-menu') {
		$link['html'] = true;
		$output .= l($link['title']. '<span>' . $link['attributes']['title'] . '</span>',$link['href'], $link);}
			else {
        $output .= l($link['title'], $link['href'], $link);
      elseif (!empty($link['title'])) {
        // Some links are actually not links, but we wrap these in <span> for adding title and class attributes.
        if (empty($link['html'])) {
          $link['title'] = check_plain($link['title']);
        $span_attributes = '';
        if (isset($link['attributes'])) {
          $span_attributes = drupal_attributes($link['attributes']);
        $output .= '<span' . $span_attributes . '>' . $link['title'] . '</span>';

      $output .= "</li>\n";

    $output .= '</ul>';
  return $output;

This solution is based on Drupal 6 version from http://ivansotof.com/2009/07/visible-description-on-drupal-primary-links

ninel’s picture

I used the code by rolkos

The YOURTHEMENAME_link function worked fine in Zen theme but didn't work at subtheme.

I tried the following:

function YOURTHEMENAME_link($variables) {
    print_r($variables); die;

Did work on Zen theme but didn't work on sub themes based on Zen themes. Any thing I missed?

artziggy’s picture

Is there a link theme wrapper so I can wrap an image in link?

dalin’s picture

By wrapper I think he means '#theme_wrappers' => [].

No, theme_link() can't be used for this because a wrapper needs to use $variables['#children'], whereas theme_link() only looks at $variables['#text']

xalexas’s picture

To add HTML tags in menu title add this to template.php

function YOURTHEMENAME_link($variables) {
$variables['options']['html'] = TRUE;
  return '' . ($variables['options']['html'] ? $variables['text'] : check_plain($variables['text'])) . '';

Of course replace YOURTHEMENAME with your theme name.

blasthaus’s picture

Doing this will expose your site to XSS injection since $variables['text'] would never be sanitized.

mlncn’s picture

Confusingly, Drupal provides a special type of render arrays for links-- instead of '#theme' => 'link' you can use '#type' => 'link' -- and more confusingly, it uses different parameters to do basically the same thing.

  $build['outlink'] = array(
    '#type' => 'link',
    '#title' => 'Central help and support site',
    '#href' => 'http://help.example.com',

See http://api.drupal.org/api/drupal/includes%21common.inc/function/drupal_p...

siefca’s picture

Caution: when adding 'query' to 'options' array, the & is changed to &amp; due to check_plain().

thedavidmeister’s picture

Try to avoid using theme_link() - https://drupal.org/node/1187032

gausarts’s picture