현대의 브라우저는 Intersection observer API를 통해 요소 확인 작업을 수행하는 더욱 우수하고 효율적인 방식을 제공합니다.
document.addEventListener("DOMContentLoaded", function() {
var lazyImages = [].slice.call(document.querySelectorAll("img.lazy"));
if ("IntersectionObserver" in window) {
let lazyImageObserver = new IntersectionObserver(function(entries, observer) {
entries.forEach(function(entry) {
if (entry.isIntersecting) {
let lazyImage = entry.target;
lazyImage.src = lazyImage.dataset.src;
lazyImage.srcset = lazyImage.dataset.srcset;
lazyImage.classList.remove("lazy");
lazyImageObserver.unobserve(lazyImage);
}
});
});
lazyImages.forEach(function(lazyImage) {
lazyImageObserver.observe(lazyImage);
});
} else {
// Possibly fall back to a more compatible method here
}
});
예시 동영상
CSS에서도 이미지 레이지 로딩을 경험할 수 있습니다.
<div class="lazy-background">
<h1>Here's a hero heading to get your attention!</h1>
<p>Here's hero copy to convince you to buy a thing!</p>
<a href="/buy-a-thing">Buy a thing!</a>
</div>
.lazy-background {
background-image: url("hero-placeholder.jpg"); /* Placeholder image */
}
.lazy-background.visible {
background-image: url("hero.jpg"); /* The final image */
}
document.addEventListener("DOMContentLoaded", function() {
var lazyBackgrounds = [].slice.call(document.querySelectorAll(".lazy-background"));
if ("IntersectionObserver" in window) {
let lazyBackgroundObserver = new IntersectionObserver(function(entries, observer) {
entries.forEach(function(entry) {
if (entry.isIntersecting) {
entry.target.classList.add("visible");
lazyBackgroundObserver.unobserve(entry.target);
}
});
});
lazyBackgrounds.forEach(function(lazyBackground) {
lazyBackgroundObserver.observe(lazyBackground);
});
}
});
위의 예를 보면 직접적인 video 컨텐츠는 source에 보관되기 때문에 다음과 같이 javascript를 통한 레이지로딩이 가능합니다.
document.addEventListener("DOMContentLoaded", function() {
var lazyVideos = [].slice.call(document.querySelectorAll("video.lazy"));
if ("IntersectionObserver" in window) {
var lazyVideoObserver = new IntersectionObserver(function(entries, observer) {
entries.forEach(function(video) {
if (video.isIntersecting) {
for (var source in video.target.children) {
var videoSource = video.target.children[source];
if (typeof videoSource.tagName === "string" && videoSource.tagName === "SOURCE") {
videoSource.src = videoSource.dataset.src;
}
}
video.target.load();
video.target.classList.remove("lazy");
lazyVideoObserver.unobserve(video.target);
}
});
});
lazyVideos.forEach(function(lazyVideo) {
lazyVideoObserver.observe(lazyVideo);
});
}
});
<video>요소를 지연 로드할 때, 모든 하위<source>요소에 걸쳐 반복하고data-src속성을src속성으로 전환해야 합니다. 이것을 완료하면 해당 요소의load방식 호출을 통해 동영상 로딩을 트리거해야 합니다.
그 후 미디어가autoplay속성마다 자동으로 재생을 시작합니다.
자바스크립트를 항상 이용할 수 있다고 가정해서는 안 됩니다. 이미지를 지연 로드하려면 자바스크립트를 사용할 수 없는 경우에 이미지를 data-* 속성에 넣어두었지만 다시 제대로 노출해주어야 합니다.
<!-- An image that eventually gets lazy loaded by JavaScript -->
<img class="lazy" src="placeholder-image.jpg" data-src="image-to-lazy-load.jpg" alt="저는 이미지입니다!">
<!-- An image that is shown if JavaScript is turned off -->
<noscript>
<img src="image-to-lazy-load.jpg" alt="저는 이미지입니다!">
</noscript>
네이티브 레이지 로딩 속성 (loading="lazy")
위의 네이티브 레이지 로딩 속성이 사용 가능한 브라우저 및 플랫폼인지 아닌지의 체크도 시도해 볼 수 있겠습니다.
if ('loading' in HTMLImageElement.prototype) alert("네이티브 레이지 로딩 지원함"); else alert("지원 안함");
위처럼 처리함으로써 얻게되는 이득은 모든 플랫폼 및 브라우저에서 레이지 로딩을 일으킬 수 있다는 것입니다.