Medium like image loading in hugo
Initially when page is loading browser request image as well(provided in src tag)
2px
image placeholder of original imageI assume you’re using a hugo theme and you want to add this feature in the theme. Even if it’s not a theme it will still work just you need to keep files in layouts/**
directory rather than themes/THEME/layouts/**
create shortcode inside themes/THEME/layouts
/shortcodes/SHORTCODENAME
.html
In my case SHORTCODENAME is lazyImage
{{ $image := (.Page.Resources.GetMatch ( .Get "src")) }}
{{ $placeholder := $image.Resize "2x q20" }}
{{ $width := or ( .Get "width") (printf "%dpx" ($image.Width)) }}
{{ $height := or ( .Get "height") (printf "%dpx" ($image.Height)) }}
<div class="image_placeholder" style="max-width: {{$width}} ; max-heigth: {{$height}}">
<div class="image_placeholder_inside">
<img src="{{ $placeholder.Permalink }}" data-src="{{ $image.Permalink }}" class="img-small lazy">
<div style="padding-bottom: {{ div (mul $image.Height 100.0) $image.Width }}%;"></div>
</div>
</div>
this code should run, so place it in any js file you want!
document.addEventListener("DOMContentLoaded",function(){
/** lazy image loading */
var lazyloadImages;
if ("IntersectionObserver" in window) {
lazyloadImages = document.querySelectorAll(".lazy");
var imageObserver = new IntersectionObserver(function (entries, observer) {
entries.forEach(function (entry) {
let image = entry.target;
var smallImg = new Image();
smallImg.src = image.src;
smallImg.onload = function () {
image.classList.add('loaded');
};
if (entry.isIntersecting) {
let ogImage = new Image();
ogImage.src = image.dataset.src;
ogImage.onload = function(){
ogImage.classList.add("loaded")
}
image.parentNode.appendChild(ogImage)
image.classList.remove("lazy");
imageObserver.unobserve(image);
}
});
});
lazyloadImages.forEach(function (image) {
imageObserver.observe(image);
});
} else {
// fall back to older browsers
let lazyloadThrottleTimeout;
lazyloadImages = e(".lazy");
function lazyload() {
if (lazyloadThrottleTimeout) {
clearTimeout(lazyloadThrottleTimeout);
}
lazyloadThrottleTimeout = setTimeout(function () {
let scrollTop = window.pageYOffset;
lazyloadImages.each(function(index,img){
if(!img)
return;
let smallImg = new Image();
smallImg.src = img.src;
smallImg.onload = function () {
img.classList.add('loaded');
};
if (e(img).offset().top < (window.innerHeight + scrollTop)) {
let ogImage = new Image();
ogImage.src = img.dataset.src;
ogImage.onload = function () {
ogImage.classList.add("loaded")
}
img.parentNode.appendChild(ogImage);
img.classList.remove('lazy');
lazyloadImages.splice(index, 1)
}
});
if (lazyloadImages.length == 0) {
document.removeEventListener("scroll", lazyload);
window.removeEventListener("resize", lazyload);
window.removeEventListener("orientationChange", lazyload);
}
}, 20);
}
document.addEventListener("scroll", lazyload);
window.addEventListener("resize", lazyload);
window.addEventListener("orientationChange", lazyload);
lazyload();
}
})
similar to js put wherever you like…
.image_placeholder_inside {
background-color: #f6f6f6;
background-size: cover;
background-repeat: no-repeat;
position: relative;
overflow: hidden;
}
.image_placeholder_inside 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);
}
.image_placeholder_inside img.loaded {
opacity: 1;
}
.image_placeholder{
display: block;
}
now in content/**/**.md
parameter | required | default | value |
---|---|---|---|
src | yes | NA | relative image path |
width | no | default image width | valid html width :- 50px,20rem,5% |
height | no | default image height | valid html height :- 50px,20rem,5% |
{{ < lazyImage src="images/someimage.jpg” > }}
{{ < lazyImage width="30rem” height="10rem” src="images/someimage.jpg” > }}
Or
{{ % lazyImage src="images/someimage.jpg” % }}
{{ % lazyImage width="30rem” height="10rem” src="images/someimage.jpg” % }}
Note
doesn't
include images in /static/img/**
folderEg.
- content/blog
|
|- Image-loading-like-medium
| |
| - index.md <--- you'll be using the shortcode here
|
|
|- images
|
- someimage.jpg
Demo
Below image is ~ 400
KB, reload the page(shift
+ f5
for hard reload) to see the effect
For any queries, Do let me know in comments down below.
Thankyou, peace out 😄