Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

drupal lazyload images plugin or implementation?

Is there any solid drupal plugin to lazyload images or has anybody implemented this?

Ideally, I would like to apply this only to a certain content type and use a plugin rather than having to code a lot / manually replace all individual nodes with references to images.

Most plugin search results are quite old or have limited documentation and litle proof of concept. I found only one interesting question here Lazy load making pages freeze/load very slow on IE? which is refering to justlazy, anybody implemented this or can recommend something please?

FYI - I already tried https://www.drupal.org/project/lazyloader but didn't seem to have any effect / couldn't make it work. I have inserted images in nodes via CKEditor. I understand that module relies on drupal image module, perhaps thats why it didn't work, i just hoped there is a plugin that replaces any normal image references with lazy load to eliminate custom setups.

like image 307
Markus Avatar asked Apr 07 '18 19:04

Markus


People also ask

How is image lazy load implemented?

Lazy Loading Techniques for images. Images on a webpage can be loaded in two ways - using the <img> tag, or using the CSS `background` property. Let's first look at the more common of the two, the <img> tag, and then move on to CSS background images.

How do I know if Lazyload is working?

If you want to test the execution of lazy loading, I can recommend that you clear your browser's cache and try reloading. In Chrome's Developer Console (F12), you can tweak the speeds and simulate modem speeds. Hit F12 -> Network tab -> Change the "No throttling" dropdown . Choose a slower speed to experiment.

What is lazy loading and how it is implemented?

Instead of loading the entire web page and rendering it to the user in one go as in bulk loading, the concept of lazy loading assists in loading only the required section and delays the remaining, until it is needed by the user.

Is lazy loading images good?

You should always use lazy loading for the images below the fold. As we explained, lazy loading will reduce the real and perceived loading time. User experience will benefit from it — and you users will thank you.


1 Answers

Creating your own module might be the easiest route though. That's what I did.

In my custom module I used bLazy, a lightweight lazy loading and multi-serving image script.

The module is quite straight-forward, I'll walk you through it:

In Drupal 7, theme_image() is responsible for outputting the <img ... /> markup for all the images rendered programmatically. That includes field images and any manual usage of theme('image', $variables).

For example;

<?php print theme('image', array('path' => $logo, 'alt' => t('Home'))); ?>

So first, you need to override the theme_image() function via hook_theme_registry_alter(), because we want to change some of the attributes of the IMG tag based on the default requirements of the bLazy script.

<?php
/**
 * Implements hook_theme_registry_alter().
 */
function CUSTOMMODULE_theme_registry_alter(&$theme_registry) {
  if (isset($theme_registry['image'])) {
    $theme_registry['image']['function'] = 'theme_CUSTOMMODULE_image';
  }
}

Then, alter the output of <img /> markup in that new theme_CUSTOMMODULE_image() function. Compare the following with theme_image() theming function:

<?php
/**
 * Overrides theme_image().
 */
function theme_CUSTOMMODULE_image($variables) {
  // Skip Blazy rendering if variables contain `.no-b-lazy` CSS class name.
  if (!empty($variables['attributes']['class']) && in_array('no-b-lazy', $variables['attributes']['class'])) {
    return theme_image($variables);
  }
  else {
    $attributes = $variables['attributes'];
    $attributes['src'] = file_create_url(drupal_get_path('module', 'CUSTOMMODULE') . '/assets/clear.gif');
    $attributes['data-src'] = file_create_url($variables['path']);
    $attributes['class'][] = 'b-lazy';
    foreach (array(
      'width',
      'height',
      'alt',
      'title',
    ) as $key) {
      if (isset($variables[$key])) {
        $attributes[$key] = $variables[$key];
      }
    }
    return '<img' . drupal_attributes($attributes) . ' />';
  }
}

I used a 1x1 pixel transparent GIF image as the placeholder image as the src attribute value, and the original image path as the data-src value. Lastly, added .b-lazy class name as the default selector.

Only remaining piece is loading the bLazy library and a simple script to load bLazy on every page, or on every theme page (non-admin).

(function ($) {
  Drupal.behaviors.CUSTOMMODULE = {
    attach: function (context, settings) {
      // @see http://dinbror.dk/blog/blazy/?ref=example-page#Options
      var options = {};
      var bLazy = new Blazy(options);
    }
  };
}(jQuery));

Within the same module, I implemented a hook_page_build() hook to attach those 2 javascript files. This way everything would be in one place.

I recommend reading the official tutorial for Adding JavaScript to your theme or module to find most suitable method for your project.

Once the module is enabled all the images passed through theme_image() would be lazy-loaded.

ADDED:

For the images added directly in .tpl.php templates, or the ones added via CKEditor in node add/edit forms, their markup should follow the same pattern as defined in the custom module, otherwise they won't lazy-load.

To make this happen I can think of two ways:

  1. Manually alter each image markup to meet bLazy's defaults. i.e.
<img src="low-res-placeholder.jpg" data-src="original-image.jpg" class="b-lazy" />
  1. Ignore everything above and use bLazy with following options to lazy load every single image on the site:
var options = {
  selector: "img",
  src: "src",
};
var bLazy = new Blazy(options);

I think both options have their pros and cons. However I think the first option is much safer and more stable over the second. Enabling lazy-load on all images may cause unexpected problems depending on site configuration.

Check out bLazy's available options. You may need to investigate further for what suits your project better.

Hope this helps.

EDIT (April 25, 2018):

I contributed my solution to the Drupal community as a module:
https://www.drupal.org/project/lazy

(I'll be adding a D8 port soon as well)

like image 53
osman Avatar answered Oct 06 '22 12:10

osman