JSLazyLoading is a lightweight performance-oriented plugin for lazy loading and multi-serving of images, that is intended for client-side optimization. Written in pure JavaScript, the plugin does not depend on third-party libraries, such as jQuery. The plugin delays the loading of images that are outside the viewport until a user scrolls to their position in the document.

The multi-serving option allows to display images dinamically, according to the device screen width or the device screen density. Retina mode is intended to display high-density images if the device screen density is high enough. In this mode high-quality images are loaded on demand without waiting of entire page load. In contrast, if you want to speed up your site to the maximum and you do not need Retina support, you can set smaller light-weight images to be displayed in mobiles and tablets instead of large images.

This plugin can reduce network traffic and increase page load speed, which is very helpful if a user has slow internet connection. Different client-side and server-side options allow you to optimize the performance and usability of your website. The plugin is compatible with both modern and older browsers. Besides, you can use it with AJAX navigation.

Installation and usage

<head>

  <!-- Include the plugin script in the head section -->
  <script type="text/javascript" src="/jslazyloading/jslazyloading.min.js"></script>

  <!-- Start the plugin -->
  <script type="text/javascript">
  
  /* Set parameters if required. You may selectively overwrite the default values, for example: */
    
  var params = {
      docReady: true,
      dataAttribute: "data-src",
      multiServing: "apache",
      multiServingType: "density",
      multiServingBreakpoints: {
          "_retina2x": "192dpi",
          "_retina3x": "288dpi"
      },
      sequentialLoading: null,
      backgroundColor: "#ededed",
      fadeInEffect: true,
      fadeInDuration: 400,
      fadeInPreserveOpacity: true,
      softMode: false,
      ajaxListener: false,
      limit: 0,
      rectangularScope: false,
      rangeY: 0,
      rangeX: 0
  };

    /* 
    * Create a new instance. The constructor may take two optional arguments: 
    * - working parameters as an object, 
    * - the plugin directory (by default, it is determined automatically).
    */
    var jsLazy = new JSLazyLoading (params);

  </script>
</head>

<!-- Rename the "src" attribute of an image to a custom "data-src" attribute -->
<img data-src="/example.jpg" width="400" height="200" alt="" />

Description of the plugin options

docReady (boolean)
Determines whether to use a built-in docReady function. If the value is false, the plugin will start immediately after an instance is created; if true (default), the plugin will start when the DOM is ready.
dataAttribute (string)
The name of the data-* attribute that identify the image source. The default value is "data-src".
sequentialLoading (null, integer)
This parameter determines whether to force the loading of images that are outside the viewport (the default value is null – disabled). While a visitor is viewing the content, images can be loaded at an interval specified in this parameter (the number of milliseconds, integer). You may also set a zero interval, in which case, all the images will be loaded immediately one after another.
placeholder (string)
According to the HTML standards, an image must have the “src” attribute. In lazy mode, this attribute must have a temporary placeholder image, which is changed to the original source when an image is in the viewport. This parameter identifies the path to the placeholder image, or a base64 encoded image (by default, the placeholder is set automatically).
loaderImage (null, string)
The path to a loader image that is shown untill the original image is loaded. By default, the loader image is set automatically. To switch off the loader image, set null as a value.
backgroundColor (null, string)
Background color of the placeholder while the original image is being loaded. (the default value is null – transparent). To change a background, set a color, for example "#000".
fadeInEffect (boolean, string)

Determines whether to display images by fading them to opaque. You will enable or disable this setting for all kinds of devices if you set this parameter to true or false respectively. You will enable the effect only for desktop browsers if you set the parameter to a string "desktop".

The fade-in effect is based on CSS3 transition and is available only for browsers that support CSS3. The main goal of lazy loading is to improve performance, so it is not reasonable to use decoration effects based on multiple JavaScript recursions or intervals. Therefore, it is disabled in older browsers.

fadeInDuration (integer)
This parameter refers to the fade-in effect and determines the number of milliseconds to run the animation (the default value is 400).
fadeInPreserveOpacity (boolean)
This parameter refers to the fade-in effect and determines the final image opacity. If the parameter is set to true (default), the opacity property will be set to the value that corresponds to CSS rules, if it is set to false, the opacity will be set to the maximum value (1). If there are no transparent (semi-transparent) images on a page, you may disable this option to increase performance.
softMode (boolean)

As the images involved in lazy loading do not contain the original source, the client browser “does not know” the image height until the image is loaded. As a result, the content may “jump” as the image loads because the browser changes the placeholder to another image. To prevent this behaviour, you can specify the image height in CSS; however, this is not possible in some cases, e.g. if you have a responsive layout.

With the soft mode (disabled by default) you do not have to set the height of your images; the height property will be set for images dynamically, according to the container width. The soft mode only works for images that have the “width” and “height” attributes (the plugin calculates the image dimensions according to the values of these attributes).

ajaxListener (boolean)
Restart the plugin when the browser sends an HTTP request if you need the new images to load in lazy mode (only images with a data-attribute will be involved). This setting is disabled by default. Another way to include new images in the plugin scope is to use a public method “refresh” (see below).
limit (integer)
By changing this parameter, you change the number of images that are checked simultaneously if they are in the viewport. The default value (0) means that only one image is tested per operation. Once this image is in the viewport, the plugin loads it and switches to another image. The smaller the number, the better the performance; however, if you have complicated layout, image loading may fail. In this case, increase this parameter up to a number that does not cause any problems, or set a large value (e.g. 1000) if you need to remove the limit.
rectangularScope (boolean)
This setting determines the shape of the viewport. If this parameter is set to true, the top, bottom, left and right borders of the viewport are taken into account, so images are loaded only if they are inside the rectangular scope. When the value is false (default), the images are loaded once they are above the bottom border of the viewport. Note: using the “Rectangular Border” option can reduce the performance to some degree if there are a large number of images involved in lazy loading on a page, because the failure limit (previous parameter) is removed automatically.
Threshold borders: X and Y axes (integer)
If you want images to load earlier, use the “rangeY” and “rangeX” parameters. Setting these parameters to 300 causes an image to load 300 pixels before it appears in the viewport. The “rangeX” parameter is enabled only if the “rectangularScope” parameter is set to true.
multiServing (boolean, string)
This setting enables/disables the multi-serving of images and determines the multi-serving mode. Acceptable values of this parameter are the following: false (disabled), "manual", "php", "apache" (see examples below).
multiServingType (string)
This setting determines the multi-serving type. Acceptable values of this parameter are the following: "width", "density". In the first instance, images are displayed according to the device screen width, in the last instance, images are displayed according to the device screen density. Available only if the “multiServing” setting is enabled (see examples below).
multiServingBreakpoints (object)
The breakpoints of multi-serving. Available only if the “multiServing” setting is enabled (see examples below).

Multi-serving of images

Image multi-serving is a way to display images dynamically according to a client device type. Retina mode is intended to display high-density images if the device screen density is high enough. In this mode high-quality images are loaded on demand without waiting of entire page load. In contrast, if you want to speed up your site to the maximum and you do not need Retina support, you can set smaller light-weight images to be displayed in mobiles and tablets instead of large images. The plugin will display a high-density or resized analogue image only if the screen parameters of a device match a breakpoint value. There can be several breakpoints, in which case, the plugin will output the image that corresponds to the closest breakpoint. The multi-serving can be manual and automatic. In the manual mode you need to set HTML attributes of images that identify analogue images. Automatic mode allows to keep the HTML unchanged, and the analogue images are displayed only if they are exist. In the automatic mode, the analogue image files must contain a postfix, and they must be located in the same folder as the original image.
Manual mode
<!-- Set data-* attributes that identify alternative sources for multi-serving. Your HTML in the manual mode must be the following: -->

<img src="/example.jpg" data-src-small="/example-small.jpg" data-src-retina2x="/example-retina2x.jpg" />
Automatic mode
<!-- Do not set data-* attributes! Just copy an image, resize it, add a postfix to the filename, and put it in the same folder as the original image. The postfix must start with an underscore (_) symbol. If an analogue does not exist, the plugin will output the original image. Your HTML in the automatic mode is: -->

<img src="/files/image.jpg" />
files/
  [..]
  image.jpg
  image_small.jpg
  image_medium.jpg
  image_retina2x.jpg
Image handlers
Two types of image handlers are available in the automatic mode of multi-serving: the Apache handler and the PHP handler. If you use Apache, it is recommended to set the Apache handler – it works faster than the PHP handler and does not changes the file extension. If you do not use Apache or the mod_rewrite, or if the Apache handler causes errors, you can set the PHP handler instead.
The following examples illustrate the various modes of image multi-serving
    // Breakpoints of the screen width in the manual mode
    var params = {
        multiServing: "manual",
        multiType: "width",
        multiServingBreakpoints: {
            "data-src-small": "420px",    
            "data-src-medium": "768px"
        }
    };
    
    // Breakpoints of the screen density in the manual mode
    var params = {
        multiServing: "manual",
        multiType: "density",
        multiServingBreakpoints: {
            "data-retina2x": "192dpi",    
            "data-retina3x": "288dpi"
        }
    };
    
    // Breakpoints of the screen width in the automatic mode (Apache handler)
    var params = {
        multiServing: "apache",
        multiType: "width",
        multiServingBreakpoints: {
            "_small": "420px",    
            "_medium": "768px"
        }
    };
    
    // Breakpoints of the screen density in the automatic mode (PHP handler)
    var params = {
        multiServing: "php",
        multiType: "density",
        multiServingBreakpoints: {
            "_retina2x": "192dpi",    
            "_retina3x": "288dpi"
        }
    };

Public methods

/* Use the "refresh" method when you need to include new images from an AJAX response in the plugin scope. Do not create a new instance. */

var jsLazy = new JSLazyLoading();

// Your code...

var request = new XMLHttpRequest();
request.open("GET", "/example.html", "true");

request.onreadystatechange = function(){
	
   if(request.readyState == 4)
   {
	
      // Your code...

      if(typeof jsLazy !== "undefined")
      {
        jsLazy.refresh();
      }
	  
   }
   
}

request.send(null);
/* The "abort" method is an emergency way to destroy an instance, remove event listeners and restore the original sources of images */

var jsLazy = new JSLazyLoading();

// Some conditions...

jsLazy.abort();

/* Use the "start" method if you need to start this instance again, after it has been stopped, if there are new images on a page */
jsLazy.start();