Jos*_*off 15 html javascript css jquery image
我正在使用基于百分比的CSS网格系统.我有一个4列的网格,每个页面的总宽度的25%.我在每个"25%单元格"中输出我的图像标签,如下所示:
<img src="foo.jpg" style="max-width:100%" />
Run Code Online (Sandbox Code Playgroud)
随着浏览器调整大小,图像也会调整大小以填充每个25%单元格的100%.浏览器选择一个高度,好像我放了"height:auto"(省略时隐含).
现在我想为此添加延迟加载功能.问题是在加载图像之前,它们在页面上的高度是未知的.浏览器必须下载图像并观察其纵横比,并计算它的高度.在此之前,所有图像的高度均为1px.由于每个图像的高度均为1px,因此它们都被视为"在视口内"并立即加载.
目前我有一个概念验证,在输出img标签之前,我在服务器上计算图像宽高比,并在数据属性中输出:
<img src="foo.jpg" style="max-width:100%" data-aspect="1.7742" />
Run Code Online (Sandbox Code Playgroud)
然后,在事件"文档就绪"时,我遍历每个图像并在延迟加载之前设置固定的"高度"值(以像素为单位):
$('img').each(function() {
var img = $(this);
var width = img.width();
var ratio = img.data('aspectratio');
var height = width / ratio;
$(this).css('height', height+'px');
});
Run Code Online (Sandbox Code Playgroud)
这似乎是有效的,因为它不再同时加载所有图像,但只在我滚动时加载图像.
但是,它似乎可能会导致新问题,例如当用户调整浏览器大小时图像会变得拉长.当一个回调触发延迟加载完成后,我必须将'height'切换回'auto'.这将照顾用户看到的图像 - 但是在缩小浏览器大小时,折叠下方的图像仍然会有不正确的"高度"值.每次调整浏览器大小时,我都必须迭代以前在首屏下方的所有图像,测量它们的更新宽度,读取它们的宽高比,并更新新的高度,然后重新触发延迟加载以处理现在高于折.如果我不这样做,由于这些图像具有错误的高度值,可能会过早或过晚触发加载.
我的问题是,除了我在这里描述的确切方法之外,还有其他方法可以延迟加载具有未知高度的图像,以及这会产生什么后果?我的方法有什么缺点,除了它是一个痛苦的程序?
小智 5
我最近遇到了类似的问题,将Isotope与Lazy 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>
Run Code Online (Sandbox Code Playgroud)
这可能比你需要的更多(因为整个.portfolio-text div是一个覆盖层,它有相当多的样式).真正的关键在于根据图像的宽度和高度计算底部填充(我在PHP模板中做了)并将其设置为我想要保存空间的项目的填充底部.
这是更优雅的解决方案,来自评论。它仍然需要编写纵横比服务器端,但使用包装器div:
<div class="lazy"><img src="foo.jpg" style="max-width:100%" data-aspect="0.75" /></div>
Run Code Online (Sandbox Code Playgroud)
然后使用 JS 我给包装器div一个padding-bottom:
$('div.lazy').livequery(function() {
var c = $(this);
var r = c.data('ar');
c.css('padding-bottom', r * 100 + '%');
});
Run Code Online (Sandbox Code Playgroud)
这给出了最终将消耗div的确切尺寸img。然后我使用以下 LESS 在padding消耗的区域内加载图像:
div.lazy {
max-width:100%;
position:relative;
img {
position:absolute;
width:100%;
height:100%;
}
}
Run Code Online (Sandbox Code Playgroud)