Reflows are bad!

If you noticed one thing in the Simple Lazy Loader made in the previous chapter, as the lazy image loaded into view it caused the page to be reflowed i.e change it's layout.

This is bad!

For example, if there is some text below the image that the user is reading, lazy loading in this way would cause the content to move downwards, because of the appearance of the image, and consequently interrupt the user's reading.

Although we do see such types of lazy loaders around the net, this is an example of a bad programming practice, developers must avoid. So how to avoid the reflow of the page once we load an image into view? This is all what this chapter is about.

A Width and Height

Perhaps the easiest solution, and the first one, which comes to the mind, is to give custom dimensions to the image or for that matter to the .lazy div.

In this way the image will already have a predefined area to fit into once it gets loaded and as a result prevent the need to reflow the page.

Let's see this in real code.

<div class="lazy"><img class="lazy-img" data-src="image.png" width="320" height="640"></div>

The dimensions given here - 320px width and 640px height - are in this case the natural dimensions of the image. If you don't know what natural dimensions are - they are the dimensions of an untouched image without any sort of custom resizing.

Add an image to a blank HTML page; its dimensions there are, in effect, its natural dimensions.

Anyways moving forward, this trick will definitely solve the reflowing issue discussed above.

However we sometimes don't right away know the dimensions of an image we need to show. Then what? Well, essentially, it all boils down to our choice of dimensions - we can give the .lazy (or even .lazy-img) any dimensions we like.

For instance we can do the following for every image on one page:

.lazy {
    width: 100%;
    height: 300px;
}

This would work perfectly fine as long as the image we are adding is roughly equal in proportion and size to these dimensions of the element .lazy. If the image doesn't meet these conditions, let's say it's relatively too small with a low resolution or of a larger height as compared to its width, then the final result might break the image's natural proportions and look extremely pathetic! Seriously.

Try altering the proportions of an image by changing its height or width only at a time. You'll see the image would look like a piece of junk!

So what we understand from this is that we need some way of getting the natural dimensions of an image and be able to include these values in the HTML. Let's discuss the choices we have to do so.

Getting the natural dimensions

Try to think on how can we get the natural dimensions of an image for whom we don't know these values. See if you can find a solution. You can rely on backend programming as well (well you've gotten one solution!)

SUB-QUIZ

We'll start with solving this problem using some manual work on our side and then move to see backend solution as well.

Manual working

Manually we can do one of the following - load the image (not lazy load) on a blank HTML page and get its dimensions using either the

  1. Developer's Console or
  2. JavaScript
HTML page with image

Using the Developer's Console

Go ahead and open this link on your browser and then inspect the element in the Developer's Console. On the Elements panel, under Computed Styles you can see the image's actual width and height values.

Note these down and write them in your HTML - either inside .lazy or .lazy-img which ever you like. Following we go with the latter approach and plug the dimensions in .lazy-img.

<div class="lazy"><img class="lazy-img" data-src="image.png" width="320" height="640"></div>

Some JavaScript

A clever technique we can use is to add a load event to the image and once it loads, then automatically calculate its natural dimensions using the naturalWidth and naturalHeight DOM properties.

<img src="imageWithUnknownDimensions.png" onload="console.log(this.naturalWidth, this.naturalHeight)">

The code here simply logs the width and height values respectively in the console which you can just like before copy and paste in your lazy image. This example was fairly basic - you can make any script you like, essentially operating on the properties naturalWidth and naturalHeight.

Following instead of logging them, we print the dimensions to the HTML page.

Output dimensions to HTML

As an exercise, and a tough one, you can make an HTML form to select an image from your local file system, use FileReader() to read it into the document and finally bring into the game naturalWidth and naturalHeight.

Backend Solution

If you don't want to go through this manual, arguably tiring work you can use a backend language to get the dimensions of an image right away as you write the markup for it in your code editor.

We will demonstrate an example in PHP. You can go with any backend language you like which has some way or other to get image dimensions.

<?php
    function getDim($src) {
        $size = getimagesize($src);
        echo 'width="' . $size[0] . '" height="' . $size[1] . '"';
    }
?>

We have constructed a function getDim() which takes an image's source URL $src and prints a string with its dimensions. The string is layed out such that it can be inlined directly within the markup of the .lazy-img.

<div class="lazy"><img class="lazy-img" data-src="image.png" <?php getDim("image.png"); ?>></div>

Absolute Dimensions Lazy Loader