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

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-29 03:20:44  来源:igfitidea点击:

Load a low-res background image first, then a high-res one

htmlcssresponsive-design

提问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.jpgor 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.jpginstead 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:

发生什么了:

  1. A low-res version of the background quickly loads.
  2. Meanwhile, the higher resolution version is loading as a hidden image.
  3. When the high-res image is loaded, jQuery swaps the div's low-res image with the high-res version.
  1. 背景的低分辨率版本快速加载。
  2. 同时,更高分辨率的版本作为隐藏图像加载。
  3. 当加载高分辨率图像时,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:

发生什么事:

  1. 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.)
  2. Meanwhile, the higher resolution photos are being loaded as hidden images (all sharing a class name of img_highres).
  3. A jQuery function is triggered each time an img_highres photo completes loading.
  4. 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.
  1. 根据 CSS 背景图像设置为每个 div 加载低分辨率图像。(请注意,CSS 还将 div 设置为预期尺寸。)
  2. 同时,更高分辨率的照片被加载为隐藏图像(所有共享一个 img_highres 类名)。
  3. 每次 img_highres 照片完成加载时都会触发一个 jQuery 函数。
  4. 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.jpgis the low-resolution version, and XOYra.jpgis 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.

如果有办法安排加载以便首先显示背景图像,这可能是我能想到的最简单的方法。

where low resolution 44k: low resolution 44k:

其中低分辨率 44k: 低分辨率 44k:

and high resolution is 1.16M high resolution is 1.16M

和高分辨率为1.16M 高分辨率为1.16M

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 srcand use the Imageclass 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/