We have two content types (Articles and Basic Page) that use the same Image (field_image) field. We are using the lazysizes js library where you need to add class="lazyload" and data-src="image-url.png" on the <img> tag.

For the Article Content type only we want to be able to lazyload the images, but we want to do in a way that does not impact the Image field on the Basic Page content type.

We initially thought that the best way to do this was to assign an Image Style with no effects and then use the mytheme_preprocess_image hook to do the following below.

Is this the correct way to modify the <img> element the way we need to? The goal is to be able to lazyload the original image without modifying it (no scalling, resizing, cropping, etc.).

function mytheme_preprocess_image(&$vars) {
  $lazy_loading = [
    'lazy_load_image_style' // Machine name of Image Style.

  if(in_array($vars['style_name'], $lazy_loading) {
    // Copy src into data-src.
    $vars['attributes']['data-src'] = $vars['attributes']['src'];

   // Add css class.
   $variables['attributes']['class'] = 'lazyload';
  • What is available if you kint $vars?
    – user72672
    Apr 19, 2018 at 2:21
  • U are using two different variables "$vars" and "$variables" !
    – zsd
    Aug 29, 2022 at 13:42

2 Answers 2


It may be easiest to use Blazy or Image Lazyloader.

If neither of those suit your needs, I would create a new field formatter class. In your custom module create a new formatter src/Plugin/Field/FieldFormatter/LazyImageFormatter.php that extends Drupal\image\Plugin\Field\FieldFormatter\ImageFormatter.php. You'll need to use the same annotation that formatter has, but then you'll only need to implement the viewElements method. Begin the method by calling $elements = parent::viewElements($items, $langcode);. Traverse $elements afterward and update the render array similar to how you have done above. Make sure to return $elements; when you're done.

This will give you a formatter on the manage display screens that you can select on whichever image fields you want on any view mode of any entity. You can even get it to work with any image style selected via your new formatter.

If you've never extended a Drupal 8 plugin check out the plugin api. Once you know how to create and extend one plugin type it's very similar process to create or extend others and you'll quickly find that the world is yours.

  • how is having a new formatter where the render array is modified different from using the Image formatter and using the mytheme_preprocess_image hook as described? It seems redundant, but maybe I am missing something about the new formatter. Apr 20, 2018 at 22:05
  • What's redundant about it? It's cleaner, clearer, extensible, and sustainable. Maybe your solution is fine in your exact use case. But why use your method when you can use similar code, put it in a different place, and get the same result, except it's cleaner, clearer, extensible, and sustainable? What happens when things change? What if you need to lazy load an image with an image style? or 3? What if you want to use that image style on one display and not lazy load it? Do you create 2 image styles? Why use an image style to trigger lazy loading an image? Why not use a formatter to do it?
    – sonfd
    Apr 20, 2018 at 22:47
  • this question came about after trying out this solution for some time now. (drupal.stackexchange.com/questions/251366/…). Apr 23, 2018 at 15:54
  • to answer your question, yes we would use different image styles. Any image styles that needed to be lazy loaded would be added to the $lazy_loading array. Creating a custom formatter is something we would want to put into a custom module and contribute it to the community, but with Blazy having Responsive Image support that is the solution we are going to go with. Apr 23, 2018 at 16:06

I've built a lazy load module for drupal 8. Should work out-of-the-box: Fancyload - lazy load images pinterest-style

Fancyload will automatically provide lazyloading of images on your website in a pinterest-style color scheme. It fetches the main color of your image and serves it until your image is loaded.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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