预加载隐藏的 CSS 图像

Posted

技术标签:

【中文标题】预加载隐藏的 CSS 图像【英文标题】:preload hidden CSS images 【发布时间】:2010-12-19 17:28:55 【问题描述】:

我正在开发一个基于 jquery 的主页,其中包含 5 个左右隐藏的 div,每个 div 都包含几个背景 css 图像。

问题是浏览器在显示父层的可见性之前不会将 css 图像加载到 DOM 中,导致当该层变得可见时图像加载缓慢。

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

CSS sprites(为此重新设计的工作量太大,并且在显示/隐藏 div 时不会真正起作用) This jQuery plugin 自动加载 CSS 背景图像(正如许多其他人所报告的那样,对我来说根本不起作用)。

通过js预加载图片:

$(function() 
function preloadImg(image) 
  var img = new Image();
  img.src = image;


preloadImg('/images/home/search_bg_selected.png');
);

此解决方案似乎将图像加载到 dom 中两次...一次在 js 加载它时,然后在加载它的 div 层变得可见时再次...所以它进行了 2 个 HTTP 调用,因此无法正常工作。

我还没有解决此问题的任何其他解决方案吗?

【问题讨论】:

【参考方案1】:

当您说其他方式时,您是指不使用 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"   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 中的图像不同的图像。【参考方案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]');

【讨论】:

【参考方案3】:

像其他解决方案一样,硬编码 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;
  
);

【讨论】:

请将第二个替换更改为:var imgUrl = backgroundImage.replace(/"/g,"").replace(/url\(|\)|"|'$/ig, ""); 这是有效的 css background-image: url('.... 例如注意单引号【参考方案4】:

CSS 预加载很容易。

示例

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

【讨论】:

【参考方案5】:

浏览器开始支持&lt;link&gt; 元素的rel="..." 属性的prefetchpreload 属性。

Addy Osmani 的 post about the preload and prefetch properties 非常棒,并描述了何时应该使用它们:

预加载是向浏览器发送请求的早期获取指令 页面所需的资源(关键脚本、Web 字体、主图)。

预取服务的用例略有不同 — 未来导航 获取资源的用户(例如视图或页面之间)和 请求需要在导航中持续存在。如果页面 A 发起一个 对页面 B 所需的关键资源的预取请求, 关键资源和导航请求可以在 平行线。如果我们在这个用例中使用预加载,它将是 在页面 A 卸载时立即取消。

元素的使用方式如下:

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

我正在设计一个包含多个步骤的表单,每个步骤都有不同的背景图像。当 Chrome 下载下一个背景图片时,此模式可解决步骤之间的“闪烁”问题。

【讨论】:

以上是关于预加载隐藏的 CSS 图像的主要内容,如果未能解决你的问题,请参考以下文章

为 CSS 动画预加载图像?

JQuery - 预加载图像(使用 JQuery / 本机 JavaScript / CSS)

CSS 使用CSS预加载图像

如何在 HTML 5 中为音频、视频、css、图像创建预加载器?

图像预加载技术(用作悬停状态 CSS 背景图像)似乎不适用于 Chrome

css 图像预加载