Change record status: 
Project: 
Introduced in branch: 
9.1.x
Introduced in version: 
9.1.0
Description: 

Attached the loading="lazy" html attribute to img tags. In the past, most lazy-loading solutions were non-native, or required custom code to work.

For example

Before:
Use a contrib module like lazy which uses a javascript library.

Or

Adding custom code like this:

function my_module_preprocess_image(&$variables) {
$variables['attributes']['loading'] = 'lazy';
}

After:
Do nothing. It’s enabled by default.

Impacts: 
Site builders, administrators, editors
Updates Done (doc team, etc.)
Online documentation: 
Not done
Theming guide: 
Not done
Module developer documentation: 
Not done
Examples project: 
Not done
Coder Review: 
Not done
Coder Upgrade: 
Not done
Other: 
Other updates done

Comments

PedroLucasnet’s picture

For some reason this is causing a conflict with my theme where some images don't get loaded at all.
Is there a way to exclude some images from loading="lazy" or disabling this on my site?
Thanks

Anybody’s picture

This is how you can do it in Drupal 7 in your template.php:

/**
 * Implements HOOK_preprocess_image.
 *
 * @param array $variables
 */
function THEMENAME_preprocess_image(&$variables) {
  // Add lazy loading attribute to all images:
  $variables['attributes']['loading'] = 'lazy';
}

See https://julian.pustkuchen.com/en/add-drupal-7-native-image-lazy-loading-...

http://www.DROWL.de || Professionelle Drupal Lösungen aus Ostwestfalen-Lippe (OWL)
http://www.webks.de || webks: websolutions kept simple - Webbasierte Lösungen die einfach überzeugen!
http://www.drupal-theming.com || Individuelle Responsive Themes

Cangurin limpiezas’s picture

any way for disable "loading="lazy"

now Google pagespeed give error if the image in lazy in above-the-fold
https://www.drupal.org/project/drupal/issues/3224714

kiwimind’s picture

If you're able to separate out the images that will show above the fold e.g. hero images, you could use a preprocess image and amend it from `loading=lazy` to `loading=eager`.

See https://developer.mozilla.org/en-US/docs/Web/HTML/Element/img#attr-loading

Cangurin limpiezas’s picture

many thanks for response @kiwimind
"you could use a preprocess image and amend it from `loading=lazy` to `loading=eager`."
How i can do this? i try find in the core where "loading=lazy" atribute is injected but i dont find with "grep -rIH 'lazy'".

i solve finally in "admin/structure/types/manage/nuestros_servicios/display" change the format to resposive image and style to "narrow"
i dont know if is a bug or what but the "loading=lazy" tag disapear of the img code

edit1 : moore info
https://www.drupal.org/project/drupal/issues/3173180
https://www.drupal.org/project/drupal/issues/3192234

joseph-dickson’s picture

Disabling lazy loading for all images with the image preprocess function in my theme...

function themehook_preprocess_image(array &$variables){
      // Disable lazy loading for all images
      $variables['attributes']['loading'] = 'eager';
}

How would I specify a specific image style or field machine name as you suggest?

joseph-dickson’s picture

Another method I discovered using Classy's image.html.twig template file I am able to set the attribute for lazy loading to eager. This will impact any images that make use of the template. Note that images added within CKEditor will remain set to lazy.

{#
/**
 * @file
 * Theme override of an image.
 *
 * Available variables:
 * - attributes: HTML attributes for the img tag.
 * - style_name: (optional) The name of the image style applied.
 *
 * @see template_preprocess_image()
 */
#}
{%
set classes = [
  style_name ? 'image-style-' ~ style_name|clean_class,
]
%}
<img{{ attributes.setAttribute('loading', 'eager').addClass(classes) }} />
joseph-dickson’s picture

deleted, code I provided doesn't work as expected. It targeted the parent div instead of the image.

jwilson3’s picture

Lighthouse penalizes lazy loaded images that appear above the fold with the following error:

Largest Contentful Paint image was lazily loaded

Above-the-fold images that are lazily loaded render later in the page lifecycle, which can delay the largest contentful paint.

One study found that:

Lazy loading only the images below the fold results in a complete reversal of the LCP regression and possibly even a slight improvement over disabling LCP entirely.

To fix this in Drupal 9 or 10 for a single above-the-fold image style, you can switch from lazy to eager loading using hook_preprocess_image_style.

/**
 * Implements template_preprocess_image_style().
 */
function MY_THEME_preprocess_image_style(&$variables) {
  $eager_styles = [
    'hero_banner',
  ];

  if (in_array($variables['style_name'], $eager_styles, TRUE)) {
    $variables['image']['#attributes']['loading'] = 'eager';
  }
}

You can also do this with responsive image styles in the following way:

/**
 * Implements template_preprocess_responsive_image().
 */
function MY_THEME_preprocess_responsive_image(&$variables) {
  $eager_styles = [
    'hero_banner',
  ];

  if (in_array($variables['responsive_image_style_id'], $eager_styles, TRUE)) {
    $variables['img_element']['#attributes']['loading'] = 'eager';
  }
}