Medium-like lazy loading of images


#1

I was looking for a good way to lazy load image son my website and stumbled upon https://www.botreetechnologies.com/blog/page-load-optimization-by-progressive-image-loading-like-medium. This post describes how to do image lazy loading similar to what medium does

  • Show a div the same size as the resulting image (so the content does not “jump” after the image is loaded)
  • Load a very small low quality placeholder and blur it in the div
  • Load the final image

I made it into a reusable shortcode

{{ $image := (.Page.Resources.GetMatch  (index .Params 0)) }}
{{ $placeholder := $image.Resize "48x q20" }} 

<div class="image_placeholder" style="max-width: {{$image.Width}}px">
<div class="placeholder" data-large="{{ $image.Permalink }}">  
  <img src="{{ $placeholder.Permalink }}" class="img-small">
  <div style="padding-bottom: {{ div (mul $image.Height 100.0) $image.Width }}%;"></div>
</div>
</div>

that can be called using

{{% post-image "image.png" %}}

but only works with page bundle images to be able to use the Hugo image resizing functionality.

The JavaScript and CSS stay the nearly same as in the post, I just adjusted them for my theme

.placeholder {
  background-color: #f6f6f6;
  background-size: cover;
  background-repeat: no-repeat;
  position: relative;
  overflow: hidden;
}

.placeholder img {
  position: absolute;
  opacity: 0;
  top: 0;
  left: 0;
  width: 100%;
  transition: opacity 1s linear;
}

.img-small {
  filter: blur(50px);
  /* this is needed so Safari keeps sharp edges */
  transform: scale(1);
}

.placeholder img.loaded {
  opacity: 1;
}

.image_placeholder{  
  display: block;
}
<script type="text/javascript">
window.onload = function() {

  var placeholder = $('.placeholder');

  placeholder.each( function(index) {
    // 1: load small image and show it
    var smallImgElement = $(this).find('.img-small');
    var img = new Image();
    img.src = smallImgElement.attr('src');
    img.onload = function () {
      smallImgElement.addClass('loaded');
    };

    // 2: load large image
    var imgLarge = new Image();
    imgLarge.src = $(this).data('large');
    imgLarge.onload = function () {
      imgLarge.classList.add('loaded');
    };
    $(this).append(imgLarge);

  })

}
</script>

You can see it in action at https://blog.kulman.sk/, especially in the Projects section.


#2

This is pretty cool. And you can also use the hasShortcode function to only load the JS in page where it is being used. :slight_smile: