【问题标题】:Lazy Loading HTML5 picture tag延迟加载 HTML5 图片标签
【发布时间】:2014-07-24 09:31:14
【问题描述】:

我一直在寻找(未成功)在使用<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>

【问题讨论】:

  • 你能显示你的标记吗?通过延迟加载,您的意思是“在视口中加载”?您找到了哪些方法,能否请您发布一个并说明如何将其应用于&lt;pictures&gt;(以及为什么不起作用)?
  • 是的,对不起,我做了假设。通过延迟加载图像,我的意思是当它们在视口中时。我见过的最常见的图片解决方案是Lazy Load plugin for jQuery
  • 嗯,that plugin is no magic。您可以轻松地将其调整为与图片中的 &lt;source&gt; 元素一起使用,而不是使用 img 的 src 属性。
  • @MrRay 我不知道浏览器如何解析(或将解析)&lt;picture&gt; 标签,但最有可能在 html 解析期间加载合适的图像(就像他们目前对 &lt;img&gt; 标签所做的那样),所以阻止它的唯一方法是在&lt;source&gt; 标签中使用data-src 属性而不是src。但即使在这种情况下也存在一些问题,所以在 LazyLoadXT 中我们开始使用&lt;br&gt; 标签而不是&lt;source&gt;ressio.github.io/lazy-load-xt/demo/picture.htm(我不记得&lt;source&gt; 标签到底有什么问题,但那样在某些浏览器中无法使用,而 &lt;br&gt; 可以)
  • 谢谢@DenisRyabov。是的,这正是我要解决的问题。我见过这个插件——它是唯一解决这个问题的插件。现在我明白为什么它使用&lt;br&gt; 标签了!

标签: javascript html image lazy-loading


【解决方案1】:

现在是 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" 属性仅适用于&lt;img /&gt; 元素(而不是&lt;picture&gt;),但请记住&lt;picture&gt; 元素并不代表实际的替换内容,@987654330 @ 元素可以(即用户看到的图像总是由&lt;img /&gt; 元素呈现,&lt;picture&gt; 元素只是意味着浏览器可以更改&lt;img src="" /&gt; 属性。From the HTML5 spec as of February 2020(强调我的):

picture 元素与外观相似的videoaudio 元素有些不同。虽然它们都包含source 元素,但当元素嵌套在picture 元素中时,source 元素的src 属性没有意义,并且资源选择算法不同。 另外,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>

【讨论】:

【解决方案2】:

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

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

【讨论】:

    【解决方案3】:

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

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

    宽度阈值设置为 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>
    

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

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

    【讨论】:

      【解决方案4】:

      在 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>
      

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-01-08
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多