I'd like to add a couple classes to the "Read more" and "Add new comment" links in my article teasers in Drupal 8.

I'd do this in Drupal 7 by doing something like this in my theme file.

function mytheme_preprocess_node(&$variables) {
  $variables['content']['links']['node']['#links']['node-readmore']['attributes']['class'][] = 'btn btn-primary';
  $variables['content']['links']['node']['#links']['comment-add']['attributes']['class'][] = 'btn btn-primary';

But this doesn't work in Drupal 8. I dumped the contents of $variables['content']['links'] and all I got was this:

$variables['...']['...'] array(2)
    '#lazy_builder' => array(2)
        string(40) "Drupal\node\NodeViewBuilder::renderLinks"
            string(1) "4"
            string(6) "teaser"
            string(2) "en"
    '#weight' => integer100

So how would I go about adding classes to these links in Drupal 8?


You can do this in a couple of different ways. By looking up the Drupal\node\NodeViewBuilder::renderLinks method, you can see how it works.

1. Implement hook_node_links_alter()

This should work for a module.

function mymodule_node_links_alter(array &$links, NodeInterface $entity, array &$context) {
  $links['node']['#links']['node-readmore']['#attributes']['class'][] = 'btn btn-primary';

2. Implement template_preprocess_links()

And I think this should work for the theme...

function mytheme_preprocess_links(&$variables) {
  // some logic enclosing this block
  $variables['node']['#links']['node-readmore']['#attributes']['class'][] = 'btn btn-primary';
  • Thanks mradcliffe. The $variables array has changed a bit in Drupal 8, so your example didn't quite work, but it got me on the right track. I did take a look at the Drupal\node\NodeViewBuilder::renderLinks method, but it wasn't clear to me how to figure out the name of the hook/preprocess function I needed to use.
    – Chris
    Jan 10 '16 at 18:02

After playing around with kint and the preprocessor function in mradcliffe's answer, here's what I used in my theme file to get this working:

function mytheme_preprocess_links(&$variables) {
    if ( isset($variables['links']['node-readmore']['attributes']) && method_exists($variables['links']['node-readmore']['attributes'], 'addClass') ) {
        $variables['links']['node-readmore']['attributes']->addClass('btn btn-primary');
    if ( isset($variables['links']['comment-add']['attributes']) && method_exists($variables['links']['comment-add']['attributes'], 'addClass') ) {
        $variables['links']['comment-add']['attributes']->addClass('btn btn-info');

Not pretty, but it works. If anyone has a better optimized solution, let me know, thanks!


I noticed my answer above actually applied the classes to the <li> that surrounds the link instead of the <a> tag itself. Upon playing with it a little more, I figured out it needs to be done like this to actually add the classes to the <a> tag:

function cabootstrap_preprocess_links(&$variables) {
    $variables['links']['node-readmore']['link']['#options']['attributes']['class'][] = 'btn btn-primary';
    $variables['links']['comment-add']['link']['#options']['attributes']['class'][] = 'btn btn-info';
  • I wonder if there's a race condition where attributes gets turned into Attribute class in some cases but not others.
    – mradcliffe
    Jan 10 '16 at 18:21
  • Yeah it's interesting, because if you want to add classes to the <li> the link is contained in, the attributes array is protected and you have to use the addClass method. Yet there is no such object and corresponding addClass method for the actual <a> link element. So I did it the usual way of adding the new classes to the attributes array.
    – Chris
    Jan 10 '16 at 18:38

If you want to modify the text of the link, use the following snippet.

function theme_preprocess_links(&$variables) {
  if (isset($variables['links']['node-readmore'])) {
    $variables['links']['node-readmore']['link']['#title'] = t('LEARN MORE');

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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