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:
- 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" />
- 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)