预加载隐藏的 CSS 图像

15

我正在制作一个基于jQuery的主页,其中包含5个或更多隐藏的div,每个div中都包含了几张背景css图片。

问题在于,浏览器直到显示父层的可见性时才将css图片加载到DOM中,导致当该层变为可见时图片缓慢加载。

我已经考虑过的解决方法:

  • CSS精灵(要重新设计太麻烦了,并且在显示/隐藏div时并不会真正起到作用)
  • 这个jQuery插件可以自动加载CSS背景图片(但据许多其他人报告,它对我并没有起作用)。
  • 通过js预加载图片:

  • $(function() {
    function preloadImg(image) {
      var img = new Image();
      img.src = image;
    }
    
    preloadImg('/images/home/search_bg_selected.png');
    });
    

    这个解决方案似乎会将图片加载到DOM中两次……一次是在js加载时,另一次是在加载它的div层变为可见时……因此它会发出两个HTTP请求,因此无法正常工作。

还有其他我漏掉的解决方案吗?

5个回答

13

当你说其他方法时,你是指不使用 JavaScript 的方法吗?

<script language="JavaScript">
function preloader() 
{
     // counter
     var i = 0;

     // create object
     imageObj = new Image();

     // set image list
     images = new Array();
     images[0]="image1.jpg"
     images[1]="image2.jpg"
     images[2]="image3.jpg"
     images[3]="image4.jpg"

     // start preloading
     for(i=0; i<=3; i++) 
     {
          imageObj.src=images[i];
     }
} 
</script>

除了使用JS之外,其他方法是将一些HTML放在页面上的某个位置,使它不可见:

<image src="picture.jpg" width="1" height="1" border="0">

或者HTML……

<img src="images/arrow-down.png" class="hiddenPic" />

...并且CSS...

.hiddenPic {
    height:1px;
    width:1px;
}

更多 JavaScript 方法:

function preload(images) {
    if (document.images) {
        var i = 0;
        var imageArray = new Array();
        imageArray = images.split(',');
        var imageObj = new Image();
        for(i=0; i<=imageArray.length-1; i++) {
            //document.write('<img src="' + imageArray[i] + '" />');// Write to page (uncomment to check images)
            imageObj.src=images[i];
        }
    }
}
然后使用类似以下方式加载图像:
<script type="text/javascript">
preload('image1.jpg,image2.jpg,image3.jpg');
</script>

谢谢所有的建议!我明天会试一下,看看哪个方法有效。我确实尝试了1x1 div方法,但是我正在使用的Rails应用程序将缓存哈希分配给图像URL的末尾...因此,浏览器将它们视为与CSS中的不同图像。 - Cory

7

像其他解决方案建议的那样硬编码URL会增加代码维护的负担。使用jQuery可以相对容易地避免这种情况,并制定通用解决方案。

此函数选择所有隐藏元素,检查它们是否具有背景图像,然后将它们加载到一个隐藏的虚拟元素中。

$(':hidden').each(function() {
  //checks for background-image tab
  var backgroundImage = $(this).css("background-image");
  if (backgroundImage != 'none') {
    var imgUrl = backgroundImage.replace(/"/g,"").replace(/url\(|\)$/ig, "");
    $('<img/>')[0].src = imgUrl;
  }
});

请将第二个replace更改为以下内容: var imgUrl = backgroundImage.replace(/"/g,"").replace(/url\(|\)|"|'$/ig, ""); 这是有效的CSS background-image: url('....,请注意单引号。 - Toskan

7

CSS预加载很简单。

示例:

body:after{
    display:none;
    content: url(img01.png) url(img02.png) url(img03.png) url(img04.png)
}

3

浏览器开始支持<link>元素的rel="..."属性中的prefetchpreload属性。

Addy Osmani的关于preload和prefetch属性的文章非常好,描述了它们应该何时使用:

Preload是一个早期获取指令,用于请求页面所需的资源(关键脚本、Web字体、主图像)。

Prefetch有一个稍微不同的用例——用户未来的导航(例如在视图或页面之间),在这种情况下,获取的资源和请求需要在导航之间保持持久。如果页面A启动了对页面B所需的关键资源的预取请求,则关键资源和导航请求可以并行完成。如果我们在这种情况下使用preload,它将立即在页面A卸载时被取消。

元素的使用方式如下:

<link rel="preload" as="image" href="https://your.url.com/yourimage.jpg" />

我正在设计一个多步骤表单,每个步骤都有不同的背景图片。这种模式能够解决Chrome在下载下一张背景图片时出现的"闪烁"问题。


2

这个解决方案似乎会将图像加载到dom中两次......一次是在js加载它时,另一次是在加载它的div层变为可见时......因此它会发出2个http请求,从而无法工作。

第二个http请求应该以304(未修改)响应,所以我想那没问题了? 另一个选项是通过jQuery加载图像,然后通过DOM内联插入背景图像,例如:

jQuery.fn.insertPreload = function(src) {
    return this.each(function() {
        var $this = $(this);
        $(new Image()).load(function(e) {
            $this.css('backgroundImage','url('+src+')');
        }).attr('src',src);
    });
};

$('div').insertPreload('[huge image source]');

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接