Breaking News
Loading...
March 9, 2016

Simple Image Lazy Load and Fade

3:12 PM

One of the quickest and easiest website performance optimizations is decreasing image loading. That means a variety of things, including minifying images with tools like ImageOptim and TinyPNG, using data URIs and sprites, and lazy loading images. It's a bit jarring when you're lazy loading images and they just appear out of nowhere which is why I love the fading in route. The page still shuffles if you aren't explicitly setting image dimensions but the fade in does provide a tiny bit of class. I've seen many solutions which accomplish this (some not very good, like my old method) so I thought I'd share my current implementation.

The HTML

We'll start by putting together the image tag with specifics:

<img data-src="/path/to/image.jpg" alt="" />

Use data-src to represent the eventual URL.

The CSS

Any image with a data-src attribute should start as invisible and eventually transition the opacity:

img {
 opacity: 1;
 transition: opacity 0.3s;
}

img[data-src] {
 opacity: 0;
}

You can probably guess at this point what we'll be doing with that attribute when an image loads...

The JavaScript

...which is removing the data-src attribute when the image has loaded:
[].forEach.call(document.querySelectorAll('img[data-src]'), function(img) {
 img.setAttribute('src', img.getAttribute('data-src'));
 img.onload = function() {
  img.removeAttribute('data-src');
 };
});

This solution does require JavaScript as a few of you have pointed out. For a fallback solution you could do this:

<noscript data-src="/path/to/image.jpg">
<img src="/path/to/image.jpg" data-src="" alt="">
</noscript>
[].forEach.call(document.querySelectorAll('noscript'), function(noscript) {
 var img = new Image();
 img.setAttribute('data-src', '');
 img.parentNode.insertBefore(img, noscript);
 img.onload = function() {
  img.removeAttribute('data-src');
 };
 img.src = noscript.getAttribute('data-src');
});

This is a super basic tutorial but considering I've seen so many other solutions, I thought I'd share what I've implemented; it works under every scenario I've tested, including History changes via AJAX (like my site does).

Of course this doesn't take into account true scroll-based lazy load but that's generally done by a plugin in your favorite JavaScript framework or a standalone component. If you're looking for a simple solution, however, this is it!

Demo script:

<p>Watch the below image lazy load and then fade in!</p>
 
 <p><img data-src="https://davidwalsh.name/demo/christina-ricci-404.jpg" class="d-image" alt=""></p>

 <script type="text/javascript">

 [].slice.apply(document.querySelectorAll('img[data-src].d-image')).forEach(function(img) {
  img.setAttribute('src', img.getAttribute('data-src'));
  img.onload = function() {
   img.removeAttribute('data-src');
  };
 });
  
 </script>

Source URL:https://davidwalsh.name/lazyload-image-fade

0 comments:

Post a Comment

 
Toggle Footer