延迟加载HTML5图片代码

时间:2014-06-03 21:44:32

标签: javascript html5 image lazy-loading

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

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

更新:
这是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>

4 个答案:

答案 0 :(得分:25)

现在是2020年2月,我很高兴地报告Google Chrome, Microsoft Edge (the Chromium-based Edge), and Mozilla Firefox都支持新的loading="lazy"属性。唯一现代的浏览器支持是Apple的Safari(iOS Safari和macOS Safari)but they've recently finished adding it to Safari's codebase,所以我希望它会在今年的某个时候发布。

loading="lazy"属性仅适用于<img />元素(而不适用于<picture>),但请记住,<picture>元素并不代表实际的替换内容<img />元素可以做到(即,用户看到的图像始终由<img />元素呈现,<picture>元素仅表示浏览器可以更改{{1 }}属性。From the HTML5 spec as of February 2020(重点是我):

<img src="" />元素与外观类似的picturevideo元素有些不同。尽管它们全部包含audio元素,但是当元素嵌套在source元素中时,source元素的src属性没有意义,并且资源选择算法也不同。 此外,picture元素本身不显示任何内容;它仅为其包含的picture元素提供上下文,使它能够从多个URL中选择

因此,这样做应该工作正常

img

答案 1 :(得分:4)

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

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

答案 2 :(得分:2)

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

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

宽度阈值设置为960px-尝试在此宽度上方和下方重新加载,以在将图像滚动到视口时查看正在下载的图像的中(-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>

和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;
      });
    }
  });

最后一个想法是,如果前后更改屏幕宽度,则会再次重复下载图像文件。如果我可以将上述方法绑定到缓存检查中,那将是黄金...

答案 3 :(得分:0)

在 web.dev 上,Google 建议可以延迟加载图片标签。
https://web.dev/browser-level-image-lazy-loading/

<块引用>

使用元素定义的图像也可以延迟加载:

<picture>
  <source media="(min-width: 800px)" srcset="large.jpg 1x, larger.jpg 2x">
  <img src="photo.jpg" loading="lazy">
</picture>
<块引用>

虽然浏览器会决定从任何元素加载哪个图像,但加载属性只需要包含在回退元素中。