javascript 延迟加载 HTML5 图片标签

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/24025464/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-28 02:01:31  来源:igfitidea点击:

Lazy Loading HTML5 picture tag

javascripthtmlimagelazy-loading

提问by MrRay

I have been searching (unsuccessfully) for a reliable method to lazy load images while using the HTML5 spec for <picture>. Most solutions/plugins out there currently rely on using data-attributes. I could be wrong, but it doesn't seem this method will work in conjunction w/ <picture>.

我一直在寻找(未成功)使用 HTML5 规范来延迟加载图像的可靠方法<picture>。目前大多数解决方案/插件都依赖于使用data-属性。我可能是错的,但这种方法似乎不能与 w/ 结合使用<picture>

I'm really just looking to be pointed in the right direction. If anyone has a solution that they're currently using, I'd love to see. Thanks!

我真的只是希望有人指出正确的方向。如果有人有他们目前正在使用的解决方案,我很乐意看到。谢谢!

UPDATE:
Here is standard markup per the HTML5 spec:

更新:
这是每个 HTML5 规范的标准标记:

<picture width="500" height="500">
    <source media="(min-width: 45em)" src="large.jpg">
    <source media="(min-width: 18em)" src="med.jpg">
    <source src="small.jpg">
    <img src="small.jpg" alt="">
</picture>

采纳答案by MrRay

For anyone still interested... After revisiting this issue, I came across a fairly new script called, Lazysizes. It's actually quite versatile, but more importantly it allows me to do lazy loading of images while utilizing the HTML5 markup as described in the OP.

对于仍然感兴趣的任何人......在重新审视这个问题之后,我遇到了一个名为Lazysizes的相当新的脚本。它实际上非常通用,但更重要的是,它允许我在使用 OP 中描述的 HTML5 标记的同时进行图像的延迟加载。

Much thanks to the creator of this script, @aFarkas.

非常感谢这个脚本的创建者,@aFarkas

回答by Dai

It's February 2020 now I'm pleased to report that Google Chrome, Microsoft Edge (the Chromium-based Edge), and Mozilla Firefoxall support the new loading="lazy"attribute. The only modern browser hold-out is Apple's Safari (both iOS Safari and macOS Safari) but they've recently finished adding it to Safari's codebase, so I expect it will be released sometime this year.

现在是 2020 年 2 月,我很高兴地报告Google Chrome、Microsoft Edge(基于 Chromium 的 Edge)和 Mozilla Firefox都支持新loading="lazy"属性。唯一支持现代浏览器的是 Apple 的 Safari(iOS Safari 和 macOS Safari),但他们最近已将其添加到 Safari 的代码库中,因此我预计它将在今年某个时候发布。

The loading="lazy"attribute is only for the <img />element (and not <picture>) but remember that the <picture>element does not represent the actual replaced-content, the <img />element does (i.e. the image that users see is always rendered by the <img />element, the <picture>element just means that the browser can change the <img src="" />attribute. From the HTML5 spec as of February 2020(emphasis mine):

loading="lazy"属性仅适用于<img />元素(而不是<picture>),但请记住,该<picture>元素并不代表实际的替换内容,该<img />元素代表(即用户看到的图像始终由该<img />元素呈现,该<picture>元素仅表示浏览器可以更改<img src="" />属性。来自 2020 年 2 月的 HTML5 规范(重点是我的):

The pictureelement is somewhat different from the similar-looking videoand audioelements. While all of them contain sourceelements, the sourceelement's srcattribute has no meaning when the element is nested within a pictureelement, and the resource selection algorithm is different. Also, the pictureelement itself does not display anything; it merely provides a context for its contained imgelement that enables it to choose from multiple URLs.

picture元素与外观相似的videoaudio元素有些不同。虽然它们都包含source元素,但当元素嵌套在元素中时,source元素的src属性没有意义picture,资源选择算法也不同。此外,picture元素本身不显示任何内容;它只是为其包含的img元素提供上下文,使其能够从多个 URL 中进行选择

So doing this should just-work:

所以这样做应该只是工作

<picture width="500" height="500">
    <source media="(min-width: 45em)" src="large.jpg" />
    <source media="(min-width: 18em)" src="med.jpg" />
    <source src="small.jpg" />
    <img src="small.jpg" alt="" loading="lazy" />
</picture>

回答by Sean Doherty

Working example of lazy loading images using the pictureelement and intersection observertested in Chrome and Firefox. Safari doesn't support intersection observer so the images are loaded immediately, and IE11 doesn't support the element so we fallback to the default img

使用在 Chrome 和 Firefox 中测试的图片元素和交集观察器延迟加载图像的工作示例。Safari 不支持相交观察者,因此图像会立即加载,而 IE11 不支持该元素,因此我们回退到默认的img

The media queries in the media attr are arbitrary and can be set to suit.

媒体属性中的媒体查询是任意的,可以设置为合适的。

The width threshold set is 960px - try a reload above and below this width to see either the medium(-m) or large(-l) variation of the image being downloaded when the image is scrolled into the viewport.

宽度阈值设置为 960 像素 - 尝试在此宽度上下重新加载,以查看当图像滚动到视口中时正在下载的图像的中 (-m) 或大 (-l) 变化。

Codepen

代码笔

<!-- Load images above the fold normally -->
<picture>
  <source srcset="img/city-m.jpg" media="(max-width: 960px)">
  <source srcset="img/city-l.jpg" media="(min-width: 961px)">
  <img class="fade-in" src="img/city-l.jpg" alt="city"/>
</picture>

<picture>
  <source srcset="img/forest-m.jpg" media="(max-width: 960px)">
  <source srcset="img/forest-l.jpg" media="(min-width: 961px)">
  <img class="fade-in" src="img/forest-l.jpg" alt="forest"/>
</picture>

<!-- Lazy load images below the fold -->
<picture class="lazy">
  <source data-srcset="img/river-m.jpg" media="(max-width: 960px)">
  <source data-srcset="img/river-l.jpg" media="(min-width: 961px)">
  <img data-srcset="img/river-l.jpg" alt="river"/>
</picture>

<picture class="lazy">
  <source data-srcset="img/desert-m.jpg" media="(max-width: 960px)">
  <source data-srcset="img/desert-l.jpg" media="(min-width: 961px)">
  <img data-srcset="img/desert-l.jpg" alt="desert"/>
</picture>

and the JS:

和 JS:

    document.addEventListener("DOMContentLoaded", function(event) {
   var lazyImages =[].slice.call(
    document.querySelectorAll(".lazy > source")
   )

   if ("IntersectionObserver" in window) {
      let lazyImageObserver = 
       new IntersectionObserver(function(entries, observer) {
          entries.forEach(function(entry) {
           if (entry.isIntersecting) {      
              let lazyImage = entry.target;
              lazyImage.srcset = lazyImage.dataset.srcset;
              lazyImage.nextElementSibling.srcset = lazyImage.dataset.srcset;
              lazyImage.nextElementSibling.classList.add('fade-in');
              lazyImage.parentElement.classList.remove("lazy");
             lazyImageObserver.unobserve(lazyImage);
            }
         });
        });

      lazyImages.forEach(function(lazyImage) {
       lazyImageObserver.observe(lazyImage);
      });
   } else {
     // Not supported, load all images immediately
    lazyImages.forEach(function(image){
        image.nextElementSibling.src = image.nextElementSibling.dataset.srcset;
      });
    }
  });

One last thought is that if you change the screen width back and forth, the image files are repeatedly downloaded again. If I could tie the above method in to a cache check then this would be golden...

最后一个想法是,如果您来回更改屏幕宽度,图像文件会再次重复下载。如果我可以将上述方法与缓存检查联系起来,那么这将是金...