预加载CSS图像


118

我有一个隐藏的联系表单,单击该按钮即可进行部署。它的字段设置为CSS背景图像,它们的出现时间总是晚于已切换的div。

我在本<head>节中使用了此代码段,但是没有运气(清除缓存后):

<script>
$(document).ready(function() {
        pic = new Image();
        pic2 = new Image();
        pic3 = new Image();
        pic.src="<?php bloginfo('template_directory'); ?>/images/inputs/input1.png";
        pic2.src="<?php bloginfo('template_directory'); ?>/images/inputs/input2.png";
        pic3.src="<?php bloginfo('template_directory'); ?>/images/inputs/input3.png";
});
</script>

我正在使用jQuery作为我的库,如果可以同时使用它来解决此问题,那将很酷。

多谢您的光临。


请显示您的代码。您如何切换此表单?
09年

1
n1313,我使用了最简单的方法:$('#toggle')。click(function(){$('#contact')。slideToggle();});
花生

Answers:


256

仅使用CSS预加载图像

在下面的代码中,我随机选择该body元素,因为它是保证存在于页面上的仅有元素之一。

为了使“技巧”发挥作用,我们将使用content可轻松允许设置要加载的多个 URL 的属性,但是如图所示,::after伪元素保持隐藏状态,因此不会渲染图像:

body::after{
   position:absolute; width:0; height:0; overflow:hidden; z-index:-1; // hide images
   content:url(img1.png) url(img2.png) url(img3.gif) url(img4.jpg);   // load images
}

演示版


最好使用Sprite图片减少HTTP请求...(如果有很多相对较小的图片),并确保图片托管在使用HTTP2的位置。


26
这太棒了!
横街

4
迄今为止的最佳技术,以其简单性和纯CSS方法实现!唯一的缺点实际上是,这些图像是与立即可见的内容同时加载的,并且不会延迟到加载主要内容之后才开始,这需要Javascript。但是,除非您要预先加载数十个图像,否则这不应该成为破坏交易的方法。
本杰明·

2
这非常适合为CSS按钮预加载悬停素材资源,这样-这样一来,当资源加载时,当您将鼠标悬停在按钮上方时,不会出现任何闪烁
Robert Petz 2014年

16
好的解决方案。但我建议不要将其应用于body,因为这些图像将被加载到引用样式表的每个页面上。相反,您应该使用.contact_form:after {...}或其他一些不太全局的类。除非,当然,除非您的联系表在每一页上;)
CloudMagick 2015年

3
@vsync,这很有意义,尤其是对于gif和小型可重用的对象。我最近遇到的情况是用于内容丰富的轮播的大型bg图片,我当然不希望到处都加载这些大文件:)
CloudMagick 2015年

30

我可以确认我的原始代码似乎有效。我随便坚持使用错误路径的图像。

这是一个测试:http : //paragraphe.org/slidetoggletest/test.html

<script>
    var pic = new Image();
    var pic2 = new Image();
    var pic3 = new Image();
    pic.src="images/inputs/input1.png";
    pic2.src="images/inputs/input2.png";
    pic3.src="images/inputs/input3.png";
</script>

在使用CSS-ONLY和此解决方案进行了几次测试之后,就我而言,这是最好的解决方案。
zequinha-bsb 2011年

感谢其最简单的方法:)
BetaCoder 2014年

4
答案中的URL不再有效。
布兰登·巴克

嗨,我重新上传了该URL(parade.org/slidetoggletest/test.html)上的内容,很抱歉错过了这个。干杯,
花生

25

使用HTML <link>标签预加载图像

我相信这个问题的大多数访问者都在寻找“如何在页面渲染开始之前预加载图像?”的答案。而针对此问题的最佳解决方案是使用<link>标签,因为<link>标签能够阻止页面的进一步呈现。看到抢先

rel当前文档和链接文档之间的关系)属性的这两个值选项与该问题最相关:

  • prefetch:页面渲染时加载给定资源
  • preload:在页面呈现开始之前加载给定资源

因此,如果要<body>标记的呈现过程开始之前加载资源(在这种情况下为图像),请使用:

<link rel="preload" as="image" href="IMAGE_URL">

如果要在<body>渲染时加载资源,但是打算以后动态使用它,并且不想在加载时间上打扰用户,请使用:

<link rel="prefetch" href="RESOURCE_URL">

值得注意的是,Mozilla浏览器引擎仅prefetch在浏览器空闲时才加载,这由nsIWebProgressListenerAPI 确定。请参阅以获取更多信息。
马修·贝克曼

1
我认为这实际上不会阻止渲染:w3c.github.io/preload “例如,应用程序可以使用preload关键字来初始化CSS资源的早期,高优先级且非渲染阻止的获取,然后由应用程序在适当的时间进行应用”
Michael Crenshaw

1
@MichaelCrenshaw是正确的,<link rel="preload">没有阻止渲染,我相信作者误解了定义。从MDN 使用rel =“ preload”,“ ...来预加载内容,您希望在页面生命周期的早期开始加载,而浏览器的主要呈现机制才开始加载。” 想法是尽快获取资源,从而使资源更有可能在需要时(例如,在<img>渲染元素时)可用。
MDMower

14

http://css-tricks.com/snippets/css/css-only-image-preloading/

技术1

将图片加载到元素的常规状态,仅将其移至背景位置。然后移动背景位置以将其显示在悬停上。

#grass { background: url(images/grass.png) no-repeat -9999px -9999px; }
#grass:hover { background-position: bottom left; }

技术2

如果有问题的元素已经应用了背景图片,并且您需要更改该图片,则以上操作将无效。通常,您会在此处使用精灵(组合的背景图片),然后仅移动背景位置。但是,如果不可能,请尝试此操作。将背景图像应用于另一个已使用但没有背景图像的页面元素。

#random-unsuspecting-element { background: url(images/grass.png) no-repeat -9999px -9999px; }
#grass:hover { background: url(images/grass.png) no-repeat; }

4
始终提供外部链接的内容。否则,如果链接断开,您的答案将毫无价值!
SRA

@Fatih +1提供了很好的链接。有3周不同的方式链接的文章的更新版本是在这里perishablepress.com/3-ways-preload-images-css-javascript-ajax
xmojmr

@xmojmr链接中没有纯CSS解决方案。
Max

10

试试这个:

var c=new Image("Path to the background image");
c.onload=function(){
   //render the form
}

使用此代码,您可以预加载背景图像,并在加载时渲染表单


mck89,谢谢,这看起来不错。但是,我应该在“ head”或内联中使用此代码吗?我的意思是,我必须用html填充它吗?
花生

您必须在头部使用它。我认为您可以在$(document).ready中使用它
mck89

6

对于预加载使用CSS设置的背景图片,我想到的最有效的答案是我发现某些代码的修改版本不起作用:

$(':hidden').each(function() {
  var backgroundImage = $(this).css("background-image");
  if (backgroundImage != 'none') {
    tempImage = new Image();
    tempImage.src = backgroundImage;
  }
});

这样做的巨大好处是,当您将来引入新的背景图像时,您不需要更新它,它将找到新的背景图像并预加载它们!


我是否正确理解为每个图像添加一个隐藏元素?并不是说它可以扫描CSS文件中的图片,对吗?:)
bvdb 2015年

5

如果要在网站上其他任何地方重复使用这些bg图像以进行表单输入,则可能要使用图像精灵。这样,您可以集中管理图像(而不是拥有pic1,pic2,pic3等...)。

对于客户端来说,精灵通常更快,因为精灵仅从服务器请求一个文件(尽管稍大),而不是多个文件。参见SO文章以获得更多好处:

CSS图像精灵

再说一遍,如果您仅将它们用于一种表单,并且您只想在用户请求联系表单时才真正加载它们,这可能根本没有帮助。

http://www.alistapart.com/articles/sprites


是的,CSS Sprites是解决之道。只需确保在启动隐藏表单(如在页面加载时)之前显示该精灵中的图像之一。
史蒂夫

1

如何将背景图片加载到隐藏的地方。这样,将在打开页面时将其加载,并且使用ajax创建表单后将不会花费任何时间:

body {
background: #ffffff url('img_tree.png') no-repeat -100px -100px;
}

1

您可以使用此jQuery插件waitForImage,也可以将图像放入隐藏的div或(width:0和height:0)中,并在图像上使用onload事件。

如果只有2-3张图像,则可以绑定事件并连锁触发它们,因此在每张图像之后都可以执行一些代码。


1

唯一的方法是对图像进行Base64编码,然后将其放置在HTML代码中,这样就无需联系服务器来下载图像。

将对来自url的图像进行编码,因此您可以复制图像文件代码并将其插入页面中,如下所示:

body {
  background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADIA...);
}

2
如果您想在CSS中再次使用相同的图片...它将不会被缓存,而您必须再次加载它。
vsync

1

如果无法修改CSS代码并使用CSS规则:before:after伪元素预加载图像,则可以使用另一种JavaScript代码遍历已加载样式表的CSS规则的方法。为了使其正常工作,应将脚本包含在HTML 样式表之后,例如,在关闭body标签之前或样式表之后。

getUrls() {
    const urlRegExp = /url\(('|")?([^'"()]+)('|")\)?/;

    let urls = [];
    for (let i = 0; i < document.styleSheets.length; i++) {
        let cssRules = document.styleSheets[i].cssRules;
        for (let j = 0; j < cssRules.length; j++) {
            let cssRule = cssRules[j];
            if (!cssRule.selectorText) {
                continue;
            }

            for (let k = 0; k < cssRule.style.length; k++) {
                let property = cssRule.style[k],
                    urlMatch = cssRule.style[property].match(urlRegExp);
                if (urlMatch !== null) {
                    urls.push(urlMatch[2]);
                }
            }
        }
    }
    return urls;
}

preloadImages() {
    return new Promise(resolve => {
        let urls = getUrls(),
            loadedCount = 0;

        const onImageLoad = () => {
            loadedCount++;
            if (urls.length === loadedCount) {
                resolve();
            }
        };

        for (var i = 0; i < urls.length; i++) {
            let image = new Image();
            image.src = urls[i];
            image.onload = onImageLoad;
        }
    });
}

document.addEventListener('DOMContentLoaded', () => {
    preloadImages().then(() => {
        // CSS images are loaded here
    });
});

0

如果页面元素及其背景图像已经在DOM中(即您没有动态创建/更改它们),则它们的背景图像将已经加载。在这一点上,您可能想看看压缩方法:)


嗯... cpharmston很好,这解释了为什么即使缓存了图像,问题仍然存在。那么,这是否意味着没有工作原理?
花生

创建较小的图像!JPEG易于压缩,有用于减小PNG大小的命令行工具(pmt.sourceforge.net/pngcrush),并且您可以减少图像中的颜色数量以减小GIF的大小。当然,您也可以快速获得更快的互联网服务;)
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.