IntersectionObserver
by tomik23
HTML
<img width="400" height="400" data-src="https://place-hold.it/400x400/15252D/fff">
<img width="400" height="400" data-src="https://place-hold.it/400x400/15252D/fff">
<img width="400" height="400" data-src="https://place-hold.it/400x400/15252D/fff">
<img width="400" height="400" data-src="https://place-hold.it/400x400/15252D/fff">
<img width="400" height="400" data-src="https://place-hold.it/400x400/15252D/fff">
<img width="400" height="400" data-src="https://place-hold.it/400x400/15252D/fff">
<img width="400" height="400" data-src="https://place-hold.it/400x400/15252D/fff">
<h2>Picture Element</h2>
<picture>
<source media="(min-width: 400px)" data-srcset="https://place-hold.it/400x400/15252D/fff">
<source media="(min-width: 200px)" data-srcset="https://place-hold.it/200x200/15252D/fff">
<img data-src="https://place-hold.it/100x100/15252D/fff">
</picture>
<picture>
<source media="(min-width: 400px)" data-srcset="https://place-hold.it/400x400/15252D/fff">
<source media="(min-width: 200px)" data-srcset="https://place-hold.it/200x200/15252D/fff">
<img data-src="https://place-hold.it/100x100/15252D/fff">
</picture>
<picture>
<source media="(min-width: 400px)" data-srcset="https://place-hold.it/400x400/15252D/fff">
<source media="(min-width: 200px)" data-srcset="https://place-hold.it/200x200/15252D/fff">
<img data-src="https://place-hold.it/100x100/15252D/fff">
</picture>
<picture>
<source media="(min-width: 400px)" data-srcset="https://place-hold.it/400x400/15252D/fff">
<source media="(min-width: 200px)" data-srcset="https://place-hold.it/200x200/15252D/fff">
<img data-src="https://place-hold.it/100x100/15252D/fff">
</picture>
<picture>
<source media="(min-width: 400px)" data-srcset="https://place-hold.it/400x400/15252D/fff">
<source media="(min-width: 200px)" data-srcset="https://place-hold.it/200x200/15252D/fff">
<img data-src="https://place-hold.it/100x100/15252D/fff">
</picture>
CSS
* {
margin: 0;
padding: 0;
}
html,
body {
height: 100%;
}
body {
width: 100%;
background: #f2f2f2;
}
html {
width: 100%;
margin: auto;
text-align: center;
}
.fade-in {
animation-name: fadeIn;
animation-duration: 300ms;
animation-timing-function: cubic-bezier(0, 0, 0.4, 1);
animation-fill-mode: forwards;
}
picture,
img {
display: block;
border: 2px solid red;
margin-bottom: 2px;
margin: auto;
}
@keyframes fadeIn {
from {
opacity: 0;
}
to {
opacity: 1;
}
}
@media (min-width: 200px) {
picture {
height: 200px;
width: 200px;
}
}
@media (min-width: 400px) {
picture {
height: 400px;
width: 400px;
}
}
JavaScript
let images = document.querySelectorAll('source, img');
if ('IntersectionObserver' in window) {
// IntersectionObserver Supported
let config = {
root: null,
rootMargin: '0px',
threshold: 0.5
};
let observer = new IntersectionObserver(onChange, config);
images.forEach(function(img) {
observer.observe(img)
});
function onChange(changes, observer) {
changes.forEach(function(change) {
if (change.intersectionRatio > 0) {
// Stop watching and load the image
loadImage(change.target);
observer.unobserve(change.target);
}
});
}
} else {
// IntersectionObserver NOT Supported
images.forEach(function(image) {
loadImage(image)
});
}
function loadImage(image) {
image.classList.add('fade-in');
if (image.dataset && image.dataset.src) {
image.src = image.dataset.src;
}
if (image.dataset && image.dataset.srcset) {
image.srcset = image.dataset.srcset;
}
}