Skip to content

Instantly share code, notes, and snippets.

@szeidler
Created March 15, 2016 08:42
Show Gist options
  • Star 16 You must be signed in to star a gist
  • Fork 7 You must be signed in to fork a gist
  • Save szeidler/3526f21a89f93a318e5d to your computer and use it in GitHub Desktop.
Save szeidler/3526f21a89f93a318e5d to your computer and use it in GitHub Desktop.
Load and render responsive image from field in Drupal 8
<?php
function _load_header_image($variables) {
if ($node = $variables['node']) {
// Load main_image
$file = $node->field_main_image->entity;
if ($file) {
$variables = array(
'responsive_image_style_id' => 'header_image',
'uri' => $file->getFileUri(),
);
// The image.factory service will check if our image is valid.
$image = \Drupal::service('image.factory')->get($file->getFileUri());
if ($image->isValid()) {
$variables['width'] = $image->getWidth();
$variables['height'] = $image->getHeight();
}
else {
$variables['width'] = $variables['height'] = NULL;
}
$logo_build = [
'#theme' => 'responsive_image',
'#width' => $variables['width'],
'#height' => $variables['height'],
'#responsive_image_style_id' => $variables['responsive_image_style_id'],
'#uri' => $variables['uri'],
];
// Add the file entity to the cache dependencies.
// This will clear our cache when this entity updates.
$renderer = \Drupal::service('renderer');
$renderer->addCacheableDependency($logo_build, $file);
// Return the render array as block content.
return $logo_build;
}
}
return NULL;
}
@jfcartier
Copy link

Thanks 👍

@eamador
Copy link

eamador commented Sep 27, 2016

Perfect example, exactly what i was looking for, thank you!

@tombola
Copy link

tombola commented Oct 14, 2016

Is it possible to pass an 'alt' attribute in this scenario? Adding a string '#alt' to $logo_build does not seem to have the expected effect.

@leymannx
Copy link

leymannx commented Oct 17, 2017

You can have responsive images much easier. It will have alt and title, too.

// Set display options.
$display_options = [
  'label' => 'hidden',
  'type' => 'responsive_image',
  'settings' => [
    'responsive_image_style' => 'MYSTYLE',
  ],
];

// Get image, apply display options.
$image = $node->get('field_MYIMAGE')->view($display_options);

// Render.
$form['accordion']['items'][$key]['image'] = render($image);

When you need to get it from a media field it's almost the same, you just need to go one level deeper.

// Get media, get image, apply display options.
$image = $node->get('field_MYMEDIA')->entity->field_media_image->view($display_options);

@adamdelaney
Copy link

@leymannx what if your image is not an image field but a reference field for a media entity?

@megclaypool
Copy link

megclaypool commented Jan 13, 2020

Thanks so much -- this code saved my butt today! I couldn't figure out how to get the width and height of a media library entity, but I had gotten the URL. Your code took me that final step to the finish line 😀

@adamdelaney, I know your question is from a million years ago, but I'll go ahead and share what I did in case anybody else stumbles across this via google. Hopefully you can adapt my specific example more broadly to your specific use cases 😀

In a custom block I've got an entity reference field set up that uses the media library to select an image. In my .theme file, I'm using hook_preprocess_block to make the image file's info available in $variables so I can use it in my twig templates:

/**
 * Implements hook_preprocess_HOOK() for Block document templates.
 */
function insert_theme_name_preprocess_block(&$variables) {
  if (!empty($variables["elements"]["#id"]) && $variables["elements"]["#id"] == 'block_machine_name') {
    if (!empty($variables['elements']['content']['insert_image_field_name'])) {

      // get the image uri from the entity reference
      $uri = $variables['content']['#block_content']->get('insert_image_field_name')->entity->get('field_media_image')->entity->uri->value;

      // get the image attached to that uri
      $image = \Drupal::service('image.factory')->get($uri);

      // verify that it's really an image, and if so store the needed info as an object in $variables
      if ($image->isValid()) {
        $variables['insert_something_descriptive_here'] = [
          'url' => file_create_url($uri),
          'width' => $image->getWidth(),
          'height' => $image->getHeight(),
        ];
      }
    }
  }
}

@MrUpsidown
Copy link

MrUpsidown commented Mar 2, 2020

@leymannx that saved my day!

I have a view returning an image with a responsive image style of type "Gallery thumbnail" and needed to have the same images in my view template but with a different responsive image style (that is "slider" to show them in a slider) and your code worked like a charm.

    // Preprocess slider images
    foreach ($view->result as $reference) {

      // Define responsive image display options
      $display_options = [
        'label'    => 'hidden',
        'type'     => 'responsive_image',
        'settings' => [
          'responsive_image_style' => 'slider',
        ],
      ];

      // Get image, apply display options
      $image = $reference->_entity->get('field_media_image')->view($display_options);

      // Render
      $responsive_image = render($image);

      // Set slider_images variable for template
      $variables['slider_images'][] = [
        'responsive_image' => $responsive_image
      ];
    }

@halkhalil
Copy link

//reference field for a media entity, with multiple values.

function MYTHEME_preprocess_node__CONTENT_TYPE(&$variables) {
  $display_options = [
    'label'    => 'hidden',
    'type'     => 'responsive_image',
    'settings' => [
      'responsive_image_style' => 'property_hero',
    ],
  ];
  foreach ($variables['node']->get('field_hero_images')->getValue() as $key => $value) {
    $media = Media::load($value['target_id']);
    $responsive_image = $media->field_media_image->view($display_options);
    $variables['hero_images'][] = [
      'hero_image' => $responsive_image
    ];
  }
}

@vistree
Copy link

vistree commented Mar 9, 2022

Hi, I like the approach from @leymannx
Any chance to add a class to the responsive image?
In twig you can add a class to responsive image style using:
{% set responsiveImage = {
'#theme': 'responsive_image',
'#responsive_image_style_id': 'display_image_gallery',
'#uri': imagePath,
'#alt': altText,
'#attributes': { class: 'img-responsive' },
} %}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment