9

So thanks to 4k4 I finally managed to get my original image URI in a field template via

item.content['#item'].entity.uri.value

and with

{{ file_url(item.content['#item'].entity.uri.value) }}

I would get the url of the original file.

I have the image style information via

item.content['#item']['#image-style']

that 'medium' is requested

A PHP solution is already available here, but how do I do this in TWIG?

There are some attempts on creating a filter for 8.1 here - but that doesn't help me currently.

1
  • Where do you want to use the image as background, exactly, a node or a page?
    – apaderno
    Jul 17, 2016 at 6:25

2 Answers 2

3

You could put the php code in the preprocess function of the field template. You have all information you need in your question.

But then you would do coding, that is already in drupal. If you have #image-style set in the image render element, then the image field should be configured for the preprocess functions that come later in the image-formatter and image-style templates to put the right src attribute in the variables for image-style.html.twig. So you can use the code that is already there by overriding this template.

See the code in /core/module/image/image.module:

function template_preprocess_image_style(&$variables) {
  $style = ImageStyle::load($variables['style_name']);

  // Determine the dimensions of the styled image.
  $dimensions = array(
    'width' => $variables['width'],
    'height' => $variables['height'],
  );

  $style->transformDimensions($dimensions, $variables['uri']);

  $variables['image'] = array(
    '#theme' => 'image',
    '#width' => $dimensions['width'],
    '#height' => $dimensions['height'],
    '#attributes' => $variables['attributes'],
    '#uri' => $style->buildUrl($variables['uri']),
    '#style_name' => $variables['style_name'],
  );
2
  • 1
    Well the thing is, that I don't want the image to render as an <img> but as a background image inline-style. Currently I either get the correct image with style as an <img> or the original file path which is much to big to use on a non-broadband connection - so I just want to get the path to the down-sampled one. And I don't want to override all image renders, just the one field. Sure I could hardwire hack the path to the style, since I know the original filename - but that would be bad. Jan 3, 2016 at 10:57
  • You don't have to override all images. You can target the one you want with theme name suggestion or you put a condition in the twig. I would choose the second, because twig debug doesn't make any suggestions for this template. So it would be easier without the need to investigate the right suggestion of this template. The hardwire hack is not advisable. You don't know wether the right image style size is in cache.
    – 4uk4
    Jan 3, 2016 at 11:11
3

I just had a need to do this as well. The right approach here is to store the image URL of the styled image into a variable (through a preprocess function), and then that variable will be available in your twig file.

I've written a function that will get any field_image file and return the original file name, or if you specify a style name, it will return the URL of the styled image.

Inside my .theme file:

function MYTHEME_preprocess_node(&$vars) {
  //get thumbnail images from field_image
  $vars['field_image_url'] = _var_image_url($vars, 'field_image', 'thumbnail');
}

//pull image field URL (original or styled)
function _var_image_url($vars, $field, $style_name = '') {
  if (!empty($vars['elements'][$field]['#object'])) {
    $fields = $vars['elements'][$field]['#object']->getFields();
    $image = $fields[$field]->getValue();

    if (!empty($image[0]['target_id'])) {
      $file = \Drupal\file\Entity\File::load($image[0]['target_id']);
      $uri = $file->getFileUri();

     if(!empty($style_name)) {
        $url = \Drupal\image\Entity\ImageStyle::load($style_name)->buildUrl($uri);
        return $url; //the styled URL
     } else {
        return file_create_url($uri); //original
     }
   }
 }
 return false;
}

Now in my twig file (node.html.twig, since I used the preprocess_node function):

<div class="banner" style="background-image:url({{ field_image_url }}"></div>

This function _var_image_url() has to be called from the THEME_preprocess_node() function because it's expecting a certain set up in the first $vars argument. If you try calling it from preprocess_page, you would need to modify it.

2
  • Thanks for this. Noticed a small typo <div class="banner" style="background-image:url({{ field_image_url }}"></div> must be <div class="banner" style="background-image:url({{ field_image_url }})"></div>
    – devunder
    May 24, 2021 at 6:48
  • Thanks! After two days searching in vain in the render array for the image's url and trying all kinds of suggested approaches, which mostly ran in WSOD's, finally a solution that worked! Why is this so difficult and most of all why is this not well documented (or simply standard functionality)? Oct 1, 2022 at 22:23

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.