madeas,
<!DOCTYPE html>
<html>
<head>
<title>Untitled</title>
<meta charset="utf-8">
<style type="text/css">
.grid{
display: flex;
flex-direction: column;
}
picture img{
width: 300px;
height: 350px;
background-color: #FF00FF;
opacity: 1;
transition: .8s 2s;
}
picture.lazy-initial .img{
opacity: 0.2;
}
</style>
</head>
<body translate="no">
<div id="app">
<responsive :list="list"></responsive>
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.6.10/vue.min.js"></script>
<script id="rendered-js">
Vue.component("responsive", {
props: ["list"],
template: `
<div class="grid">
<template v-for="(f, index) in list" :key="index">
<picture class="lazy lazy-initial">
<source :srcset="f.large" media="(min-width: 62em)">
<source :srcset="f.medium" media="(min-width: 48em)">
<source :srcset="f.small" media="(min-width: 36em)">
<img :alt="f.caption" :data-src="f.img" src >
</picture>
</template>
</div>` });
new Vue({
el: "#app",
created() {
this.list = JSON.parse(`
[
{
"large": "190x127",
"medium": "350x234",
"small": "520x347",
"img": "330x220"
},
{
"large": "190x127",
"medium": "350x234",
"small": "520x347",
"img": "330x220"
},
{
"large": "190x127",
"medium": "350x234",
"small": "520x347",
"img": "330x220"
},
{
"large": "190x127",
"medium": "350x234",
"small": "520x347",
"img": "330x220"
},
{
"large": "190x127",
"medium": "350x234",
"small": "520x347",
"img": "330x220"
}
]
`);
} });
// Update the image source on elements in the picture element
function loadImage(picture) {
var sources = picture.children;
var loadingPath = "https://via.placeholder.com/";
for(var s=0; s<sources.length; s++) {
// remove the lazy-initial class when the full image is loaded to unblur
sources[s].addEventListener('load', image => {
image.target.closest("picture").classList.remove("lazy-initial")
}, false);
// update the src or srcset urls
if (sources[s].hasAttribute("srcset")) {
sources[s].setAttribute("srcset",loadingPath + sources[s].getAttribute("srcset"));
} else {
sources[s].src = loadingPath + sources[s].dataset.src ;
}
}
}
// Stop observing this image and load its source
function lazyLoad(elements) {
elements.forEach(item => {
if (item.intersectionRatio > 0) {
observer.unobserve(item.target);
loadImage(item.target);
};
});
};
// Set up the intersection observer to detect when to define
// and load the real image source
var options = {
rootMargin: "100px",
threshold: 1.0
};
var observer = new IntersectionObserver(lazyLoad, options);
// Watch for all pictures with a "lazy" class
var pictures = document.querySelectorAll('picture.lazy');
pictures.forEach(pic => {
observer.observe(pic);
});
</script>
</body>
</html>