延迟加载HTML5图片代码

MrR*_*Ray 8 javascript html5 lazy-loading image

我一直在搜索(不成功)一个可靠的方法来延迟加载图像,同时使用HTML5规范<picture>.目前大多数解决方案/插件都依赖于使用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>
Run Code Online (Sandbox Code Playgroud)

Dai*_*Dai 50

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

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

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

所以这样做应该可以正常工作

<picture width="500" height="500">
    <source media="(min-width: 45em)" srcset="large.jpg" />
    <source media="(min-width: 18em)" srcset="med.jpg" />
    <source src="small.jpg" />
    <img src="small.jpg" alt="Photo of a turboencabulator" loading="lazy" />
</picture>
Run Code Online (Sandbox Code Playgroud)


MrR*_*Ray 5

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

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


Sea*_*rty 5

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

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

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

代码笔

<!-- 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>
Run Code Online (Sandbox Code Playgroud)

和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;
      });
    }
  });
Run Code Online (Sandbox Code Playgroud)

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