2

The input in file field.html.twig is normally like this:

{% for item in items %}
<div{{ attributes }}>{{ item.content }}</div>
{% endfor %}

And you get the output in HTML like this:

<div><img src="path/to/image/image.png" alt="my wonderful image"></div>

But I want to add a class to img-tag. How do I receive the following output:

<div><img class="img-fluid" src="path/to/image/image.png" alt="my wonderful image"></div>

I am looking for a solution like this (solution in another post), but it is not working. Can anybody help?

1

5 Answers 5

7

I'd prefer to avoid editing templates for such simple things as adding just classes. I'd recommend to edit templates only if you really need to make changes to the markup.

For adding a simple class to your image all you need is the following snippet placed in your custom (sub-)theme's *.theme file. (Replace MYTHEME with the actual machine name of your theme). This one identifies the image by its image style (so ensure to have an unique image style applied to your image):

/**
 * Implements template_preprocess_image().
 */
function MYTHEME_preprocess_image(&$variables) {

  // Check the image style.
  if ($variables['style_name'] == 'img_fluid') {

    // Set class.
    $variables['attributes']['class'][] = 'img-fluid';
  }
}

If you are fine with adding the class not to the img tag directly, but to its wrapping container you could also use the following snippet. You can broaden the if-request as you like to only fire on certain content types (as you maybe use the same field in other content types as well), p.e. check for $variables['element']['#object']->bundle(). Replace field_MYIMAGE with your actual field name.

/**
 * Implements template_preprocess_field().
 */
function MYTHEME_preprocess_field(&$variables) {

  // Check for your image field.
  if ($variables['element']['#field_name'] == 'field_MYIMAGE') {

    // Set class.
    $variables['attributes']['class'][] = 'img-fluid';
  }
}
3
  • Do I have a possibility to add a class to an image-tag in the body-field of a node? Authors can add an image inside the eck-editor. In this case I do not have an extra image field. The image is than e.g. inside the body-field. Can I add a class to the image using a preprocess function even in this case?
    – lesley n.
    Jul 12, 2018 at 11:21
  • @lesleyn. – With a little bit of JS, sure. Or directly in the textarea when you switch to "Source" you can edit the <img> directly. You see, your options are quite limited. Multi-purpose body fields are hell. I mean it. Switch to drupal.org/project/paragraphs and let editors build their content modularly. Then they'd have an extra paragraph type let's say "Image" with an image field, with all the features that come along with it: preprocessing, image styles, alt and title etc.
    – leymannx
    Jul 12, 2018 at 11:28
  • Thanks a lot for your infos! I am going to solve it with embed module.
    – lesley n.
    Jul 12, 2018 at 12:17
3

You can first add theme suggestions for image elements based on the image style. Add this in your mytheme.theme file:

/**
 * Implements hook_theme_suggestions_HOOK_alter().
 *
 * Add theme suggestions for img elements.
 */
function mytheme_suggestions_image_alter(array &$suggestions, array $variables) {
  if (isset($variables['style_name']) && !is_null($variables['style_name'])) {
    $suggestion = 'image__' . $variables['style_name'];
    $suggestion = str_replace('-', '_', $suggestion);
    $suggestions[] = $suggestion;
  }
}

Then if you inspect your image you will see a theme suggestion based on the image style of that image. For example if you have an image style 'blog_item_teaser':

<!-- FILE NAME SUGGESTIONS:
   * image--blog-item-teaser.html.twig
   x image.html.twig
-->

so now you can copy image.html.twig into your own theme and rename it to image--blog-item-teaser.html.twig and you can add your class there:

<img{{ attributes.addClass('card-img-top') }} />

Of course, this will be applied to all images that use that image style.

0

You can first add attributes to your item and then add a class to it. Like this:

{{ item.content, item.attributes.addClass('img-fluid') }}

1
  • 2
    I have put it in my template and after clearing the cache I got the info "The website encountered an unexpected error. Please try again later."
    – lesley n.
    Jun 25, 2018 at 14:03
0

2 is correct. However; it comes with drawbacks. Namely, there is nothing in the array passed via $variables to differentiate one img field from another. In my case, I wanted to add classes to support Bootstrap functionality. BUT; I only want to do that in certain cases.

One line of jQuery did does the trick.

  $(".people-photo > img").addClass("card-img-top").removeAttr("width height");

And bonus: same line allowed me to easily get rid of height/width attributes that overrides Bootstrap.

0

In the view you created, select URL to image from Formatter.

screenshot

Then, in the view template file, you can get the image URL using code similar to the following one.

<img class="img-fluid" src="{{ fields.field_cover_photo.content }}" alt="test">

field_cover_photo is the field machine name, in my case.

1
  • As it’s currently written, your answer is unclear. Please edit to add additional details that will help others understand how this addresses the question asked. You can find more information on how to write good answers in the help center.
    – Community Bot
    Jul 20, 2022 at 8:04

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.