16

I'm trying to set up a slideshow that's unique to each page. The code for this needs to be in page.html.twig. I've got the slideshow mostly working, but I can only call the full image URL, not a custom image style of a specific size. How can I modify this code to call a specific image size?

{% for key, item in node.field_slides %}
{% if node.field_slides[key].entity %}
<figure class="swiper-slide">
    <img class="swiper-image" src="{{ file_url(node.field_slides[key].entity.uri.value) }}" alt="{{ node.field_slides[key].alt  }}" />

    {% if node.field_slides[key].title %}
    <figcaption class="swiper-caption">
        <div class="swiper-user-content user-content">
            {{ node.field_slides[key].title|striptags("<a>,<h1>,<h2>,<h3>,<h4>,<h5>,<h6>,<ol>,<p>,<table>,<ul>")|raw }}
        </div><!--/.swiper-user-content.user-content-->
    </figcaption><!--/.swiper-caption-->
    {% endif %}
</figure><!--/.swiper-slide-->
{% endif %}
{% endfor %}

The bit where I'm calling the URL is:

{{ file_url(node.field_slides[key].entity.uri.value) }}

I've tried doing {{ dump(node.field_slides[key]) }} to see if there was any data I could use, but every time I do that, I just get 500 error.

Any help would be greatly appreciated; I'm very new to Drupal, coming from WordPress. I think this is the last major hurdle before I can finish up this theme for my client.

7 Answers 7

45

Replace the image tag

<img class="swiper-image" src="{{ file_url(node.field_slides[key].entity.uri.value) }}" alt="{{ node.field_slides[key].alt  }}" />

with a render array for the image style:

{% set imagestyle = {
  '#theme':      'image_style',
  '#style_name': 'medium',
  '#uri':        node.field_slides[key].entity.uri.value,
  '#alt':        node.field_slides[key].alt,
  '#attributes': { class: 'swiper-image' },
} %}

{{ imagestyle }}

Edit:

There is a new filter in the module Twig Tweak. Now you can generate the image style url in twig directly from an uri or url:

{{ node.field_slides[key].entity.uri.value | image_style('thumbnail') }} 
3
  • This solution worked for me after installing the Twig Tweak module - thanks. Commented Dec 6, 2018 at 5:48
  • 1
    This worked for me right away! Thanks @4k4! You saved my life today! Commented Feb 25, 2019 at 20:24
  • Works great. You should add '#width' and '#height' as well. Other modules could need to use them for rendering. Commented Nov 8, 2019 at 14:17
6

Just an update for the 4k4 answer.

To print entity fields (eg. paragraph), we can use this:

<img src="{{ item.entity.field_image.entity.uri.value | image_style('image_style') }}" alt="{{item.entity.field_image.alt}}"/>

1
  • I tried this, and it does not work for Paragraph. {{ file_url(paragraph.field_custom_image.entity.uri.value | image_style('image_style')) }}
    – CocoSkin
    Commented Feb 5 at 17:55
5

To print a responsive image style:

{% set responsiveimagestyle = {
    '#theme': 'responsive_image',
    '#responsive_image_style_id': 'responsive_image_style',
    '#uri': node.field_slides[key].entity.uri.value,
    '#attributes': { class: 'swiper-image', alt: 'text', title: 'text' },
} %}

{{ responsiveimagestyle }}
2
  • 1
    i am not supposed to make such comments but u are a genius :)
    – Matoeil
    Commented Jan 29, 2021 at 15:45
  • Yes, you can also build a render array for a response image style, but then use the render element '#type': 'responsive_image' to include the library.
    – 4uk4
    Commented Sep 21, 2021 at 19:01
3

I recently needed this myself with the twist that I wanted to provide a default (svg) image when no image was uploaded. Twig Tweak makes this possible while still allowing me to control the output via Drupal's user interface.

In my case, I'm styling a comment, so I want to render the user picture, and I'd like to use the "thumbnail" image style. This is difficult because typically an entity field that's not the primary entity of your template can't just be rendered.

  1. Install Twig Tweak module.
  2. Create a new view mode for the user (I named my "compact").
  3. Set the user_picture field with whatever image style output you want to use in "Manage Display". For me that was "thumbnail", but it won't be visible in the code sample.
  4. Override the comment.html.twig and add the following line where ever makes sense for your use case.

    {{ comment.uid.entity.user_picture|view('compact') }}
    

Twig tweak provides this "view" method which will now render my user_picture field with the "compact" view mode settings I've already defined in Drupal. If I want to change image styles later, I can do so through the user interface without needing to make any additional modifications to my twig templates. Also, this will support Drupal's "default image" settings as well without having to codify that into the twig or preprocess hooks in some other way.

1

If you need to access through a nested paragraph (field_image is on parent paragraph) use this:

{% set paragraph_parent = paragraph.getParentEntity() %}

{% set responsiveimagestyle = {
    '#theme': 'responsive_image',
    '#responsive_image_style_id': 'hero_responsive',
    '#uri': paragraph_parent.field_image.entity.field_media_image.entity.fileuri,
    '#attributes': { class: 'swiper-image', alt: paragraph_parent.field_image.entity.field_media_image.alt },
} %}
0

Thanks to these replies , i used it, in combination with foundation grid classes , to toggle between two different responsive images for a carrousel item paragraph, depending on wether we wanna display a text panel or not ( the image dimensions being changed )

if it can help anyone :

{% set classes = [
  'paragraph',
  paragraph.bundle|clean_class,
  view_mode ? 'paragraph--view-mode--' ~ view_mode|clean_class,
  not paragraph.isPublished() ? 'paragraph--unpublished',
] %}

{% if  content.field_carrousel_item_title.0 or content.field_carrousel_item_text.0 %}
  {% set carrousel_structure="img+text" %}
  {# Changement du style d'image #}
  {% set image_uri =content.field_carrousel_item_image[0]['#media'].field_media_image_1|file_uri %}
  {% if image_uri is not null %}
    {% set image_alt =content.field_carrousel_item_image[0]['#media'].field_media_image_1.alt %}
    {% set image_w_style = {
      '#theme':      'responsive_image',
      '#responsive_image_style_id': 'carrousel--with-text-panel',
      '#uri':        image_uri,
      '#alt':        image_alt,
      '#attributes': { class: 'carrousel--with-text-panel' },
    } %}
  {% endif %}
{% endif %}

{% block paragraph %}
  <div{{ attributes.addClass(classes) }}>
    {% block content %}
      {% if  content.field_carrousel_item_link[0]['#url']|render %}
        {% set field_link = content.field_carrousel_item_link[0]['#url']|render %}
        <a class="carrousel-item__link stretched-link" href="{{ field_link }}"><span class="show-for-sr">lien vers le contenu associé</span></a>
      {% endif %}
      <div class="grid-x">
        {% if carrousel_structure=="img+text" %}
          <div class="cell carrousel-item__image large-8 medium-12">
            {{ image_w_style }}
          </div>
          <div class="cell carrousel-item__text large-4 medium-12">
            <div class="carrousel-item__title">
              {{ content.field_carrousel_item_title }}
            </div>
            {{ content.field_carrousel_item_text }}
          </div>
        {% else %}
          <div class="cell carrousel-item__image carrousel--image-full-width large-12 medium-12">
            {{ content.field_carrousel_item_image }}
          </div>
        {% endif %}
      </div>
    {% endblock %}
  </div>
{% endblock paragraph %}
0

Since the accepted answer, a new field formatter "URL to image" was added to Drupal.

You can just select it in display settings, and there will be no need to do it programmatically:

enter image description here

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