延迟加载“响应”图像(未知高度)

时间:2014-05-01 21:24:28

标签: javascript jquery html css image

我正在使用基于百分比的CSS网格系统。我有一个有4列的网格,每个网页的总宽度的25%。我在每个" 25%单元格内输出我的图像标签"像这样:

<img src="foo.jpg" style="max-width:100%" />

随着浏览器调整大小,图像也会调整大小以填充每个25%单元格的100%。浏览器选择一个高度,好像我已经放了&#34; height:auto&#34; (省略时隐含)。

现在我想为此添加延迟加载功能。问题是在加载图像之前,它们在页面上的高度是未知的。浏览器必须下载图像&amp;观察其纵横比,并计算它的高度。在此之前,所有图像的高度均为1px。由于每个图像的高度均为1px,因此它们都被视为&#34;在视口中#34;并立即加载。

目前我有一个概念证明,在输出img标签之前,我在服务器上计算图像宽高比,并在数据属性中输出:

<img src="foo.jpg" style="max-width:100%" data-aspect="1.7742" />

然后,在事件&#34;文件准备好&#34;后,我遍历每个图像并设置一个固定的高度&#39;延迟加载前的像素值:

$('img').each(function() {
        var img = $(this);
        var width = img.width();
        var ratio = img.data('aspectratio');
        var height = width / ratio;
        $(this).css('height', height+'px');
    });

这似乎是有效的,因为它不再同时加载所有图像,但只在我滚动时加载图像。

然而,似乎它可能会导致新问题,例如当用户调整浏览器大小时图像会变得拉长。我不得不切换高度&#39;回到&#39; auto&#39;当一个回调触发延迟加载完成时。这将照顾用户看到的图像 - 但是折叠下方的图像仍然会有不正确的高度&#39;调整大小的浏览器的值。每次调整浏览器大小时,我都必须迭代以前在首屏下方的所有图像,测量它们的更新宽度,读取它们的宽高比,并更新新的高度,然后重新触发延迟加载以处理现在高于折。如果我不这样做,由于这些图像的高度值错误,可能会过早或过晚触发加载。

我的问题是,除了我在此描述的确切方法之外,还有其他任何方法可以延迟加载未知高度的图像,以及这会产生什么后果?我的方法有什么缺点,除了编程很痛苦吗?

4 个答案:

答案 0 :(得分:5)

我最近遇到了类似的问题,在响应式布局中将IsotopeLazy Load相结合。同位素在加载页面时根据图像的宽度和高度确定布局,因此最初,项目都是重叠的,因为Isotope没有计算正确的大小。

为了确保占位符项保存空间,我使用了你提到的填充底部技巧:http://thisisthat.co.uk/notebook/2013-10-07-lazy-loading-responsive-images(虽然它可能不是那么精确的帖子。)这是我的标记:

    <article class="portfolio-item">
        <a class="portfolio-link" href="img/gallery/thumb90.jpg" style="padding-bottom: 66.2%">
            <div class="portfolio-image-wrapper">
                <img class="portfolio-image" data-original="img/gallery/thumb90.jpg" width="1000" height="662">
            </div>
            <div class="portfolio-text">
                <h1 class="portfolio-item-name">
                    <span href="#" class="icon" data-icon="e"></span>
                    <span class="portfolio-item-tags">Bridals</span>
                </h1>
            </div>
        </a>
    </article>

这可能比你需要的更多(因为整个.portfolio-text div是一个覆盖层,它有相当多的样式)。真正的关键是根据图像的宽度和高度计算底部填充(我在PHP模板中做了)并将其设置为我想要节省空间的项目的填充底部。

答案 1 :(得分:4)

更干净:

  1. 将图像的高度和宽度设置为任意大的数字(如2000px x 1000px
  2. 将以下CSS应用于每个所需图像(可能通过共享类):
    max-width: 100%height: auto
  3. 笑得宽:)
  4. 这种方法的功劳归于Github用户干,在this Github issue

    中给出

答案 2 :(得分:2)

这是评论中更优雅的解决方案。它仍然需要编写纵横比服务器端,但需要使用包装器div

<div class="lazy"><img src="foo.jpg" style="max-width:100%" data-aspect="0.75" /></div>

然后使用JS我给包装器div一个padding-bottom

$('div.lazy').livequery(function() {
    var c = $(this);
    var r = c.data('ar');
    c.css('padding-bottom', r * 100 + '%');
});

这为div提供了img最终消耗的确切尺寸。然后我使用以下LESS在padding消耗的区域内加载图像:

div.lazy {
  max-width:100%;
  position:relative;
  img {
    position:absolute;
    width:100%;
    height:100%;
  }
}

答案 3 :(得分:1)

如果您的图片中包含heightwidth道具(WordPress的默认设置),并且在1x1px中加载了src gif图像-默认情况下在某些插件中(看着您-{ {1}}),然后将此小野兽插入脚本中的wp-smush事件中,它将在懒惰加载时自动修复图像的讨厌的垂直跳动,我知道这是旧帖子,但这是现代的js解决方案:

docready