English 中文(简体)
当图像在视口内时如何使图像懒加载?
原标题:How do you make images load lazily only when they are in the viewport?

我最近看到很多网站,主要是教程网站,它们有很多图片,只有在图片进入视口后才加载页面下方的图片。

How would I go about doing this? As you scroll down the page the images who were below the viewport fade in

最佳回答
问题回答

<img loading="lazy" 可以在没有任何 JavaScript 的情况下完成

我们现在越来越支持这种标准化无JavaScript方法,这非常令人兴奋!

你可以在以下代码片段中看到它的工作方式。

要查看实际上是否是懒加载,请在网络选项卡中打开Chrome DevTools

然后,当您向下滚动片段时,您会发现只有在您看到它们时才会加载图像。

我还添加了一个可选的JavaScript按钮,以表明您可以从JavaScript中将 lazy 更改回默认的 eager ,然后图像将立即开始加载。

document.getElementById( load-now ).addEventListener( click , function(){
  for (const img of document.getElementsByTagName( img )) {
    img.loading =  eager ;
  }
});
.separator {
    height: 1000px;
    width: 100px;
    border: 5px solid red;
}
img {
    height: 340px;
    border: 5px solid black;
}
  #load-now {
  border: 5px solid black;
  }
<div id="load-now">Click me to load all images now!</div>
<div><img loading="lazy" height="340" src="https://upload.wikimedia.org/wikipedia/commons/5/56/Donald_Trump_official_portrait.jpg"></div>
<div class="separator"></div>
<div><img loading="lazy" height="340" src="https://upload.wikimedia.org/wikipedia/commons/8/8d/President_Barack_Obama.jpg"></div>
<div class="separator"></div>
<div><img loading="lazy" height="340" src="https://upload.wikimedia.org/wikipedia/commons/d/d4/George-W-Bush.jpeg"></div>
<div class="separator"></div>
<div><img loading="lazy" height="340" src="https://upload.wikimedia.org/wikipedia/commons/d/d3/Bill_Clinton.jpg"></div>
<div class="separator"></div>
<div><img loading="lazy" height="340" src="https://upload.wikimedia.org/wikipedia/commons/9/90/George_H._W._Bush%2C_President_of_the_United_States%2C_1989_official_portrait_%28cropped%29.jpg"></div>
<div class="separator"></div>
<div><img loading="lazy" height="340" src="https://upload.wikimedia.org/wikipedia/commons/1/16/Official_Portrait_of_President_Reagan_1981.jpg"></div>

这个方法真的很不错的一点是它完全符合SEO友好,因为src=属性包含了像往常一样的图像源,另请参阅: 使用语义标记进行延迟图像加载

测试过 Chromium 81 和 Firefox 77.0.1,两者均工作正常并懒加载。

IntersectionObserver 最小可运行示例

这是一种JavaScript方法,在实施img loading="lazy"之前起作用。

这基本上是在https://appelsiini.net/projects/lazyload/中使用的技术,该技术在https://stackoverflow.com/a/2322042/895245中提到。

网络API已经发展得如此之多,以至于从头开始编码并不难!

var observer = new IntersectionObserver(
    (entries, observer) => {
        entries.forEach(entry => {
            if (entry.intersectionRatio > 0.0) {
                img = entry.target;
                if (!img.hasAttribute( src )) {
                    alert( will load the image!!! );
                    img.setAttribute( src , img.dataset.src);
                }
            }
        });
    },
    {}
)
for (let img of document.getElementsByTagName( img )) {
    observer.observe(img);
}
.separator {
    height: 1000px;
    width: 100px;
    border: 5px solid red;
}
img {
    height: 340px;
    border: 5px solid black;
}
<div><img data-src="https://upload.wikimedia.org/wikipedia/commons/5/56/Donald_Trump_official_portrait.jpg"></div>
<div class="separator"></div>
<div><img data-src="https://upload.wikimedia.org/wikipedia/commons/8/8d/President_Barack_Obama.jpg"></div>
<div class="separator"></div>
<div><img data-src="https://upload.wikimedia.org/wikipedia/commons/d/d4/George-W-Bush.jpeg"></div>
<div class="separator"></div>
<div><img data-src="https://upload.wikimedia.org/wikipedia/commons/d/d3/Bill_Clinton.jpg"></div>
<div class="separator"></div>
<div><img data-src="https://upload.wikimedia.org/wikipedia/commons/9/90/George_H._W._Bush%2C_President_of_the_United_States%2C_1989_official_portrait_%28cropped%29.jpg"></div>
<div class="separator"></div>
<div><img data-src="https://upload.wikimedia.org/wikipedia/commons/1/16/Official_Portrait_of_President_Reagan_1981.jpg"></div>

完整页面演示:https://cirosantilli.com/web-cheat/js-image-load-viewport.html

GitHub 上游:https://github.com/cirosantilli/cirosantilli.github.io/blob/1f637bf4791b115777300f48f427f0a6bb409fc1/web-cheat/js-image-load-viewport.html

这个技巧只不过是以下几种技巧的结合:

已在Chromium 76中测试。

将负载顺序更改为最近的顺序。

这是我在 loading="lazy" 之后缺少的最后一个用例:一个下载的方法,但会将下载顺序更改为首先在视口上下载,然后在下方下载,最后在上方下载:更改已在页面上的图像的加载顺序

也许我们可以利用 querySelectorAll() 解决 jQuery 查找某些类的下一个/上一个元素,但不一定是兄弟元素,然后从 JavaScript 中删除图像中的 loading=lazy!这既能优美降级,又有助于 SEO。

最后一个问题是如何获得第一个可见元素:

我还没有看到一个非常好的解决方案。

懒加载视频

不确定为什么,但Chromium 81和Firefox 77.0.1都无法进行懒加载视频,现在不确定为什么只为img做了这件事。

Chromium 81已经实现了iframe,这也是YouTube嵌入使用的,而Firefox 77.0.1则没有:使用jquery实现延迟加载iframe(延迟src http调用)。

一個簡單純粹的JavaScript解決方案:

<script>
  document.addEventListener("DOMContentLoaded", function () {
    let images = document.querySelectorAll("img[data-src]");
    function loadImagesLazily(e) {
      for (let i = 0; i < images.length; i++) {
        let rect = images[i].getBoundingClientRect();
        if (images[i].hasAttribute("data-src")
          && rect.bottom > 0 && rect.top < window.innerHeight
          && rect.right > 0 && rect.left < window.innerWidth) {
          images[i].setAttribute("src", images[i].getAttribute("data-src"));
          images[i].removeAttribute("data-src");
        }
      }
    };

    window.addEventListener( scroll , loadImagesLazily);
    window.addEventListener( resize , loadImagesLazily);
    loadImagesLazily();
  });
</script>

用占位符替换您的图像(例如,只需更改“src”属性以使图像无法加载,但仍可访问URL),然后将窗口滚动事件绑定到一个函数,该函数将在当前滚动位置找到所有图像,并将图像src交换到真实的img标记中。

这是代码。它未经测试,但这应该是基本思路:

<img src="" realsrc="/myimage.png" />

$(document).ready(function(){

  $(window).scroll(function(){
    $( img[realsrc] ).each(function(i){
      var t = $(this);
      if(t.position().top > ($(window).scrollTop()+$(window).height()){
        t.attr( src , t.attr( realsrc )); // trigger the image load
        t.removeAttr( realsrc ); // so we only process this image once
      }
    });
  })

});




相关问题
selected text in iframe

How to get a selected text inside a iframe. I my page i m having a iframe which is editable true. So how can i get the selected text in that iframe.

How to fire event handlers on the link using javascript

I would like to click a link in my page using javascript. I would like to Fire event handlers on the link without navigating. How can this be done? This has to work both in firefox and Internet ...

How to Add script codes before the </body> tag ASP.NET

Heres the problem, In Masterpage, the google analytics code were pasted before the end of body tag. In ASPX page, I need to generate a script (google addItem tracker) using codebehind ClientScript ...

Clipboard access using Javascript - sans Flash?

Is there a reliable way to access the client machine s clipboard using Javascript? I continue to run into permissions issues when attempting to do this. How does Google Docs do this? Do they use ...

javascript debugging question

I have a large javascript which I didn t write but I need to use it and I m slowely going trough it trying to figure out what does it do and how, I m using alert to print out what it does but now I ...

Parsing date like twitter

I ve made a little forum and I want parse the date on newest posts like twitter, you know "posted 40 minutes ago ","posted 1 hour ago"... What s the best way ? Thanx.

热门标签