Html 先加载低分辨率背景图片,然后加载高分辨率背景图片
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/27934548/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Load a low-res background image first, then a high-res one
提问by Ingwie Phoenix
I am trying to optimize the size of my site when it is being outputted to the client. I am down to 1.9MB and 29KB when caching. The issue is that the first load contains an image which is very unoptimized for mobile devices; it has a 1080p resolution.
当我的网站被输出到客户端时,我试图优化我的网站的大小。缓存时我减少到 1.9MB 和 29KB。问题是第一次加载包含一个非常不适合移动设备优化的图像;它具有 1080p 分辨率。
So I am looking for a method that allows me to first load a low-res version (min.bg.jpg
) and once the site has loaded, use a high-res version - or even one with a resolution close to the device being used (NNNxNNN.bg.jpg
or just bg.jpg
).
因此,我正在寻找一种方法,该方法允许我首先加载低分辨率版本 ( min.bg.jpg
),一旦网站加载完毕,就使用高分辨率版本 - 甚至是分辨率接近正在使用的设备的 (NNNxNNN.bg.jpg
或仅bg.jpg
) .
The background is set using CSS just like everyone would expect. Its applied to the body and the entire statement looks like this:
正如每个人所期望的那样,背景是使用 CSS 设置的。它应用于正文,整个语句如下所示:
body {
background: url("/cdn/theme/images/bg.jpg");
color: white;
height: 100%;
width: 100%;
background-repeat: no-repeat;
background-position: 50% 50%;
background-attachment: fixed;
}
Now, I want to change that to use min.bg.jpg
instead for the first load, and then something like this:
现在,我想将其更改min.bg.jpg
为用于第一次加载,然后是这样的:
jQuery(function(){
jQuery("body").[...]
});
Which way do I go on asynchronously downloading the new background, and then inserting it as the new CSS background image?
我应该以哪种方式异步下载新背景,然后将其作为新的 CSS 背景图像插入?
To show some differences, here is an example of the main and mini version I am using for testing:
为了显示一些差异,以下是我用于测试的主要版本和迷你版本的示例:
[email protected] ~/Work/BIRD3/cdn/theme/images $ file *.jpg
bg.jpg: JPEG image data, EXIF standard
min.bg.jpg: JPEG image data, JFIF standard 1.01
[email protected] ~/Work/BIRD3/cdn/theme/images $ du -h *.jpg
1,0M bg.jpg
620K min.bg.jpg
采纳答案by Alan M.
Here's the method I use...
这是我使用的方法...
CSS:
CSS:
#div_whatever {
position: whatever;
background-repeat: no-repeat;
background-position: whatever whatever;
background-image: url(dir/image.jpg);
/* image.jpg is a low-resolution at 30% quality. */
}
#img_highQuality {
display: none;
}
HTML:
HTML:
<img id="img_highQuality" src="dir/image.png">
<!-- img.png is a full-resolution image. -->
<div id="div_whatever"></div>
JQUERY:
查询:
$("#img_highQuality").off().on("load", function() {
$("#div_whatever").css({
"background-image" : "url(dir/image.png)"
});
});
// Side note: I usually define CSS arrays because
// I inevitably want to go back and add another
// property at some point.
What happens:
发生什么了:
- A low-res version of the background quickly loads.
- Meanwhile, the higher resolution version is loading as a hidden image.
- When the high-res image is loaded, jQuery swaps the div's low-res image with the high-res version.
- 背景的低分辨率版本快速加载。
- 同时,更高分辨率的版本作为隐藏图像加载。
- 当加载高分辨率图像时,jQuery 将 div 的低分辨率图像与高分辨率版本交换。
PURE JS VERSION
纯JS版本
This example would be efficient for changing one to many elements.
此示例对于将一个元素更改为多个元素非常有效。
CSS:
CSS:
.hidden {
display: none;
}
#div_whatever {
position: whatever;
background-repeat: no-repeat;
background-position: whatever whatever;
background-image: url(dir/image.jpg);
/* image.jpg is a low-resolution at 30% quality. */
}
HTML:
HTML:
<div id="div_whatever"></div>
<img id="img_whatever" class="hidden" src="dir/image.png" onload="upgradeImage(this);">
JAVASCRIPT:
爪哇脚本:
function upgradeImage(object) {
var id = object.id;
var target = "div_" + id.substring(4);
document.getElementById(target).style.backgroundImage = "url(" + object.src + ")";
}
UPDATE / ENHANCEMENT (1/31/2017)
更新/增强 (1/31/2017)
This enhancement is inspired by gdbj's excellent point that my solution results in the image path being specified in three locations. Although I didn't use gdbj's addClass() technique, the following jQuery code is modified to extract the image path (rather than it being hardwired into the jQuery code). More importantly, this version allows for multiple low-res to high-res image substitutions.
此增强功能的灵感来自gdbj的出色之处,即我的解决方案会在三个位置指定图像路径。尽管我没有使用gdbj的 addClass() 技术,但修改了以下 jQuery 代码以提取图像路径(而不是将其硬连接到 jQuery 代码中)。更重要的是,这个版本允许多个低分辨率到高分辨率的图像替换。
CSS
CSS
.img_highres {
display: none;
}
#div_whatever1 {
width: 100px;
height: 100px;
background-repeat: no-repeat;
background-position: center center;
background-image: url(PATH_TO_LOW_RES_PHOTO_1);
}
#div_whatever2 {
width: 200px;
height: 200px;
background-repeat: no-repeat;
background-position: center center;
background-image: url(PATH_TO_LOW_RES_PHOTO_2);
}
HTML
HTML
<div id="div_whatever1"></div>
<img id="img_whatever1" class="img_highres" src="PATH_TO_HIGH_RES_PHOTO_1">
<div id="div_whatever2"></div>
<img id="img_whatever2" class="img_highres" src="PATH_TO_HIGH_RES_PHOTO_2">
JQUERY
查询
$(function() {
$(".img_highres").off().on("load", function() {
var id = $(this).attr("id");
var highres = $(this).attr("src").toString();
var target = "#div_" + id.substring(4);
$(target).css("background-image", "url(" + highres + ")");
});
});
What's happens:
发生什么事:
- Low res images are loaded for each of the divs based on their CSS background-image settings. (Note that the CSS also sets the div to the intended dimensions.)
- Meanwhile, the higher resolution photos are being loaded as hidden images (all sharing a class name of img_highres).
- A jQuery function is triggered each time an img_highres photo completes loading.
- The jQuery function reads the image src path, and changes the background image of the corresponding div. In the example above, the naming convention is "div_[name]" for the visible divs and "img_[same name]" for the high res images loaded in the background.
- 根据 CSS 背景图像设置为每个 div 加载低分辨率图像。(请注意,CSS 还将 div 设置为预期尺寸。)
- 同时,更高分辨率的照片被加载为隐藏图像(所有共享一个 img_highres 类名)。
- 每次 img_highres 照片完成加载时都会触发一个 jQuery 函数。
- jQuery 函数读取图片 src 路径,并更改相应 div 的背景图片。在上面的例子中,可见 div 的命名约定是“div_[name]”,背景中加载的高分辨率图像的命名约定是“img_[same name]”。
回答by Milche Patern
Let's try a basic one :
让我们尝试一个基本的:
<img border="0"
style="background:url(http://i.stack.imgur.com/zWfJ5.jpg) no-repeat;
width:1920px;
height:1200px"
src="http://i.stack.imgur.com/XOYra.jpg" width="1920" height="1200" />
zWfJ5.jpg
is the low-resolution version, and XOYra.jpg
is the high-resolution version.
zWfJ5.jpg
是低分辨率版本,XOYra.jpg
是高分辨率版本。
If there is a way to arrange the loading so the background-image displays first, this could be the simplest i can think of.
如果有办法安排加载以便首先显示背景图像,这可能是我能想到的最简单的方法。
result :
结果 :
jsFiddled here( this needs a bigger image for loading comparison. )
jsFiddled here(这需要更大的图像进行加载比较。)
回答by user7956100
A bit late, but you can use this extremely simple solution: You can put the two images in the css background:
有点晚了,但是您可以使用这个非常简单的解决方案:您可以将两个图像放在 css 背景中:
background-image: url("high-res.jpg"),url("low-res.jpg");
The browser will display the low-res image fist, then display the high-res over the low-res when it has been loaded.
浏览器将首先显示低分辨率图像,然后在加载后在低分辨率上显示高分辨率。
回答by steffcarrington
I would normally optimise the image using Grunt or an online tool such as Tiny PNG to reduce the file size.
我通常会使用 Grunt 或 Tiny PNG 等在线工具优化图像以减小文件大小。
Then you could choose to defer the loading of the images, I found the following article helpful when it came to defering images - https://www.feedthebot.com/pagespeed/defer-images.html
然后您可以选择延迟加载图像,我发现以下文章在延迟图像方面很有帮助 - https://www.feedthebot.com/pagespeed/defer-images.html
The article discusses using a base64 image for the initial loading and then defering the loading of the high quality image. The image mark up mentioned in the article is as follows...
本文讨论了使用 base64 图像进行初始加载,然后推迟加载高质量图像。文章中提到的图片标注如下...
<img src="data:image/png;base64,R0lGODlhAQABAAD/ACwAAAAAAQABAAACADs=" data-src="your-image-here">
<img src="data:image/png;base64,R0lGODlhAQABAAD/ACwAAAAAAQABAAACADs=" data-src="your-image-here">
The JavaScript mentioned in the article is as follows...
文章中提到的JavaScript如下...
<script type="text/javascript" async>
function init() {
var imgDefer = document.getElementsByTagName('img');
for (var i=0; i<imgDefer.length; i++) {
if(imgDefer[i].getAttribute('data-src')) {
imgDefer[i].setAttribute('src',imgDefer[i].getAttribute('data-src'));
}
}
}
window.onload = init;
</script>
I hope this helps.
我希望这有帮助。
回答by Nguyen Tan Dat
All answers above mostly work with a little adjustment, but here is the way I think short and simple to kick off.
上面的所有答案大部分都经过了一些调整,但这是我认为简短而简单的开始方式。
Note:
笔记:
- Uncomment the code load the high-resolution image for usage, a sleep function is just for simulating a slow network.
- Actually, this method does not load 2 resources (low and high) simultaneous, but it's acceptable because low resource won't take much time to load.
- Just copy whole code and run for a quick check.
- 取消注释加载高分辨率图像以供使用,睡眠功能仅用于模拟慢速网络。
- 实际上,这种方法不会同时加载 2 个资源(低和高),但它是可以接受的,因为低资源不会花费太多时间来加载。
- 只需复制整个代码并运行以进行快速检查。
<!DOCTYPE html>
<html>
<head>
<script src="http://code.jquery.com/jquery-2.1.1.min.js"></script>
<style type="text/css">
</style>
</head>
<body>
<!-- Load low res image first -->
<img style="width: 400px; height: auto;" alt="" src="https://s3-ap-southeast-1.amazonaws.com/wheredat/banner-low-quality/banner_20180725_123048.jpg" onload="upgrade(this)">
</body>
<script type="text/javascript">
function upgrade(image){
// After load low res image, remove onload listener.
// Remove onload listener.
$(image).prop("onload", null);
// Load high resolution image.
// $(image).attr('src', 'https://s3-ap-southeast-1.amazonaws.com/wheredat/banner/banner_20180725_123048.jpeg');
// Simulate slow network, after 1.5s, the high res image loads.
sleep(1500).then(() => {
// Do something after the sleep!
// Load a high resolution image.
$(image).attr('src', 'https://s3-ap-southeast-1.amazonaws.com/wheredat/banner/banner_20180725_123048.jpeg');
});
}
// Sleep time expects milliseconds
function sleep (time) {
return new Promise((resolve) => setTimeout(resolve, time));
}
</script>
</html>
回答by FThompson
On Ubuntu / Chrome 71, Milche's answer does not work consistently for me and the higher resolution image (via img src
) often loads and resolves before the lower resolution image (via css background
) even begins downloading.
在 Ubuntu / Chrome 71 上,Milche 的答案对我来说并不一致,并且更高分辨率的图像(通过img src
)通常在较低分辨率的图像(通过 css background
)甚至开始下载之前加载和解析。
My solution is to start with the lower res image as the src
and use the Image
class to create an unattached <img>
instance with the high res image. Once it loads, then update the existing <img>
source with the high res image source.
我的解决方案是从较低分辨率的图像开始,src
并使用Image
该类创建一个<img>
带有高分辨率图像的独立实例。加载后,<img>
使用高分辨率图像源更新现有源。
HTML:
HTML:
<img id='my-image' src='low-res.png' alt='Title' width='1920px' height='1200px'>
JavaScript:
JavaScript:
window.addEventListener('load', function() {
loadHighResImage(document.getElementById('my-image'), 'high-res.png')
})
function loadHighResImage(elem, highResUrl) {
let image = new Image()
image.addEventListener('load', () => elem.src = highResUrl)
image.src = highResUrl
}
Fiddle: https://jsfiddle.net/25aqmd67/
小提琴:https: //jsfiddle.net/25aqmd67/
This approach works for lower res images that are simply scaled down as well.
这种方法也适用于简单缩小的低分辨率图像。
回答by Caleb Hutchinson
Have you tried using CSS sprites to help get what you want? http://css-tricks.com/css-sprites/
您是否尝试过使用 CSS 精灵来帮助获得您想要的东西?http://css-tricks.com/css-sprites/