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

时间:2017-03-29 12:14:22

标签: css google-chrome preloading

我使用以下技术预先加载在悬停按钮时作为CSS背景图像应用的图像:

#preload_area {
  background-image: 
    url(../images/image1.svg),
    url(../images/image2.svg);
  width: 0px;
  height: 0px;
  display: inline;
}

还尝试以这种方式预加载一个图像:

#preload_area {
  background: url(../images/image1.svg) -9999px -9999px no-repeat;
}

这一切都不起作用:硬刷新后,第一次悬停我的按钮时,我仍然看到一个闪烁(对应于加载悬停图像)。显然,在第一次之后不再眨眼了。

为什么不使用Chrome? (它适用于Firefox)

7 个答案:

答案 0 :(得分:0)

现场演示: http://blackmiaool.com/soa/43093224/

没有人承诺会加载不可见的图像。浏览器有权不预加载您的隐形图像,因此您的问题中的css方法可能无法在某些浏览器中使用。上面的演示由我自己编写。它实际上在屏幕上呈现图像以保证图像被加载。

HTML:

<!DOCTYPE html>
<html>

<head>
    <meta charset="utf-8" />
    <title>test</title>

</head>

<body>
    <h1 style="color:white;text-align:center;">Try to hover</h1>
    <div class="show-area"></div>
    <link rel="stylesheet" href="style.css">

    <script src="../js/jquery.min.js"></script>
    <script>
        function preloadImage(src, cb) {
            //create a image
            const $dom = $("<img />", {
                src: src
            });

            //check whether the image is already loaded
            if ($dom[0].naturalWidth) {
                cb && cb();
                return;
            }

            //Put the image at the left bottom of the screen, and set its opacity to 0.01 to keep it from people eyes. 
            //Since it's actually rendered on the screen, the browser must load the image
            $dom.css({
                opacity: 0.01,
                position: 'fixed',
                bottom: 0,
                left: 0,
                height: 1,
                width: 1,
                'z-index': 10000,
                'pointer-events': 'none',
            });

            $(document.body).append($dom);

            //listen its `load` event to remove it and invoke callback
            $dom.on("load", function() {
                $dom.remove();
                cb && cb();
            });
        }

        //try to get the urls in the css file, and preload them
        $("link").each(function() {
            const href = $(this).attr("href");
            $.get(href, function(style) {
                const urls = [];
                let match = style.match(/url\([\s\S]+?\)/g);

                match.forEach(function(str) {
                    str = str.replace(/\s/g, "")
                        .replace(/^url\(/, "")
                        .replace(/\)$/, "");
                    let url = str.match(/^["']?([\S]+?)["']?$/);
                    if (!url || !url[1]) {
                        console.warn("Can't find url of " + str);
                    } else {
                        url = url[1];
                        preloadImage(url);
                    }
                });
            });
        });
    </script>

</body>

</html>

的CSS:

body{
    margin: 0;
    background-color: black;
}
.show-area {    
    height: 100px;  
    width: 300px;
    margin: auto;
    margin-top: 100px;
    background: url( ./1.jpg) no-repeat center;
    background-size: contain;
}

.show-area:hover {
    background-image: url("./2.jpg ");
}

答案 1 :(得分:0)

为什么它无法在Chrome上运行?因为所有浏览器厂商都想要最快的浏览器他们不会加载无关的资产。

您想要一种跨浏览器的预加载方式吗?使用精灵,如[CBroe]建议的那样。这种解决方案已存在多年,并且坚如磐石。任何其他技巧,使图像不可见,今天可以工作但明天就会被打破。

答案 2 :(得分:0)

在CSS中预加载实际上并不意味着文件在其他所有内容之前加载它只是意味着它是从CSS文件中排队下载的第一个资源。

这意味着您的HTML已经从服务器检索到,并且可能已经在CSS之前排队或下载了其他资源。在所有HTML内容之后加载CSS预加载图像并不罕见。

现在,虽然图像在队列中比CSS中引用的其他资源更早,但并不意味着它在其他资源之前返回。如果文件的大小大于正在排队的其他文件,则可能需要比同时下载的其他文件更长的时间。

查看Chrome发生情况的一种方法是转到您的网页并导航到Chrome Devtools中的“网络”标签,然后刷新页面。它将显示何时加载每个项目以及从服务器接收该项目的时间长度的详细信息。

根据您正在加载的图像和用例,还有其他几种选择。

1)如果文件大小很大,下载时间过长会弄清楚如何减小文件大小。

2)如果您控制了用户正在导航的页面,您可以在前一页面中预取该缓存的图像。

3)除了CSS之外,您还可以尝试使用HTML预加载。 HTML预加载我认为目前只支持Chrome,所以它可能适合这种情况。将以下内容添加到HTML的开头。

<link rel="preload" as="image" href="image1.svg">
<link rel="preload" as="image" href="image2.svg">

答案 3 :(得分:0)

使用镀铬进行测试,接缝图像已加载。眨眼是因为我认为放置了图像。更好地了解一下这个测试。

A test with a very big image

div#preload_area::before {
 content: " ";
 background: url(http://gfsnt.no/oen/foto/Haegefjell_Jan_2013_Large.jpg) no-repeat;
}

div#preload_area {
  width: 50%;
  height:100vh;
}

div#preload_area:hover {
   background: url(http://gfsnt.no/oen/foto/Haegefjell_Jan_2013_Large.jpg);
   background-repeat:no-repeat;
   background-size:100% auto;
}

答案 4 :(得分:0)

恕我直言,这不是预加载。它只是加载,当你悬停按钮时,你可以使用技巧来显示正确的图像。

如果你真的想要预加载,或者,根据我的理解你的需要,&#34;你想要图像已经在那里,当你试图悬停按钮&#34;时,你有不同的选择:

  • 预取:

mpmath

为此添加一个好处是&#34;链接预取没有同源限制&#34;。

  • 预压:

def lni(z): i0 = mpmath.besseli(0, z) # may become a big number logi0 = mpmath.log(i0) # logarithm brings big number into sensible range return float(logi0) # convert back to normal floating point

使用&#34; preload&#34;,必须下载资源,而预取并不总是如此。

Chrome,Opera,Android浏览器以及其他一些浏览器支持Preload,但没有Firefox&amp;其他。更多详情here

这些技术在css-tricks.com

上有更深入的描述

希望这会对你有所帮助。

答案 5 :(得分:0)

如果您不想要加载间隙,可以使用精灵图像,或者可以将背景图像设置为base64编码图像。在这种情况下,加载css文件时始终会加载图像。

.myImg {
    background-image: url(data:image/svg+xml;base64,PD9...);
}

在这里,您可以将svg图像转换为base64:http://b64.io

答案 6 :(得分:0)

我最近在我的博客http://anggit.com中将其用于“返回顶部”按钮。 它会对你有用吗?

CSS:

<style>
#to_top {
    display: block;
    width: 48px;
    height: 48px;
    overflow: hidden;
}
#to_top img { /* in case the actual image size is over 48px */
    width: 48px;
    height: 48px;
}
#to_top:hover #image-1 { /* hover will remove the 1st image, the 2nd image will appear */
    display: none;
}
</style>

HTML:

<a id="to_top" href="#">
    <img id="image-1" src="image48x48.png" alt="Top" />
    <img id="image-2" src="image48x48-hover.png" alt="Top" />
</a>