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