I always try to use the core functions for linking in drupal, but I'm not able to add html markup like <a href="..."><span>Link text</span></a>. Any ideas?

3 Answers 3


Use the Markup class:

use Drupal\Core\Link;
use Drupal\Core\Url;
use Drupal\Core\Render\Markup;

$url = Url::fromUri('http://www.example.com');     
$linkText = 'My link <br> containing tags';
$linkMarkup = Markup::create($linkText);
$link = Link::fromTextAndUrl($linkMarkup, $url);
$link = $link->toRenderable();

If you build a render array for the link you can simply place the html markup in #markup:

$build['my_link'] = [
  '#type' => 'link',
  '#title' => [
    '#markup' => 'My link <br> containing tags',
  '#url' => Url::fromUri('http://www.example.com'),

If this is a Drupal field, I find it easier and cleaner to do it in hook_preprocess_field:

  if ($variables['field_name'] == 'field_myfield') {
    foreach ($variables['items'] as $key => $item) {
      $variables['items'][$key]['content']['#options']['attributes']['class'][] = 'hl__button';
      $variables['items'][$key]['content']['#options']['attributes']['title'] = t('Visit link for "@title"', ['@title' => $item['content']['#title']]);

      $variables['items'][$key]['content']['#title'] = new FormattableMarkup('<span class="hl__button__text">@title</span>', [
        '@title' => $item['content']['#title'],

That way you can affect other attributes or add more.

Your Answer

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

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