How to render a multi-value Media field in a Drupal theme twig template

Published Jul 16, 2022
Updated Jul 17, 2022
By Simon
Table of contents

In this Druppet (Drupal snippet) we are going to look at getting the value of a multi-value media image field and then render the images in a chosen image style. We will first look at how we can render the media reference field which includes all the values and comes with the ability to edit each image directly from the front-end UI. Then we will be looking at how to render each image separately with a twig for-in loop and using a formatter or more technically a Twig filter to render the images in a custom image style.

To render a field in Drupal is pretty easy and the same is true with a media reference field. All we need to do in our custom node template is render the field like any other field. The following code will render a media reference field with the machine name of field_media_gallery.

 {{ content.field_media_gallery }} 
multi-value Drupal media image field rendered
A rendered Media Image with the contextual edit link visible on hover.

The great thing about this is individual images are rendered as separate entities, which means they come wrapped and have their own edit button. We can also control the view mode, image style, and what fields are rendered with each image all from the Drupal UI.

However, sometimes we may want to render the images without a wrapper or add custom wrappers with classes from our theme's CSS framework or make a specific structure so we can implement a custom image viewer. In these cases, we will need to dig a little deeper, so let's do that.

Rendering Drupal Media Images in a node template with custom code

The process for doing this is similar to looping through a multi-value Drupal field except that since the Media references field references an entity type the way we access the values is slightly different. In fact, we can do it without needing to add a module as we had to with the list field.

First, let's set a few variables.

{# Image Media Field with machine name field_media_gallery#}
{% set img_media_arr = node.field_media_gallery %}
{% set length_image_media = node.field_media_gallery|length %}

The second variable isn't needed but I will check that we have more than 1 image. Also notice that we use the node object. The node object gives access to the raw values where the content adds Drupal field markup.

Now we have our media images array we can loop through it using the twig for tag.

{% for img_item in img_media_arr %}
  {# Add code here #}
{% endfor %}

Inside the for loop, we first need to get the URI of each image item in the array. In the following code, you can see that we set or assign a value to the img_uri variable.

{% set img_uri = img_item.entity.field_media_image.entity.fileuri %}

We can also get the alt with this pattern.

{% set img_alt = img_item.entity.field_media_image.alt %}

The value of the entity item .entity.field_media_image.entity.fileuri returns the public URI and will look some like this public://2022-06/my_image_1.jpg. This value isn't of much use as is but it can be used with an image style filter to generate a path to the image with the set style.

{{ img_uri | image_style('large') }}

By adding this to a img tag with the alt and wrapping it in a div with a bootstrap style we now have a nice grid of images.

 <div class="col-12 col-md-6"> <img src="{{ img_uri | image_style('large') }}" alt="{{ img_alt }}"></div>

Here is the complete code with a condition to only show if more than 1 image is present.

{% if length_image_media > 1 %}
   {% for img_item in img_media_arr %}

     {% set img_uri = img_item.entity.field_media_image.entity.fileuri %}
     {% set img_alt = img_item.entity.field_media_image.alt %}

     <div class="col-12 col-md-6"><img src="{{ img_uri | image_style('large') }}" alt="{{ img_alt }}"></div>

  {% endfor %}
{% endif %}

That's it, you can now build out the markup in your node twig templates for galleries and sliders or even masonry layouts.

Thanks for reading and if frontend development and design interest you be sure to sign up for my newsletter. Bye for now.