Image preload methods (for use as hover CSS-based background images) don't seem to work in Chrome

I use the following technique to preload images that are used as CSS background images when hovering buttons:

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

Also tried to preload only one image:

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

None of this works: after a hard update, when I press my button for the first time, I still see a blink (corresponding to loading the hover image). Obviously, after this first moment it no longer flashes.

Why is Chrome not working? (it works in Firefox)

+5
source share
7 answers

Live Demo: http://blackmiaool.com/soa/43093224/

No one promises that invisible images will be uploaded. Browsers have the right not to preload your invisible images, so the css approach in your question may not work in some browsers. The demo above is written by me. It actually displays the image on the screen to guarantee image loading.

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 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 "); } 
0
source

Why doesn't it work in Chrome? Because all browser vendors want the fastest browser. They will not load unprotected assets.

Do you need cross browser preview mode? Use the sprite as suggested by [CBroe]. This solution has been around for ages and solid. Any other trick that renders the image invisible can work today, but tomorrow it will be broken.

0
source

Preloading in CSS doesn't really mean that the file is loading in front of everything else, it just means that the first resource will be queued for loading from your CSS file.

This means that your HTML has already been extracted from the server and probably already queued or loaded other resources before CSS. It is not uncommon for CSS pre-loaded images to load after all HTML content.

Now, when the image will be in the queue earlier than other resources specified in CSS, this does not mean that it returns to these other resources. If the file size is larger than other files in the queue, downloading may take longer than other files that are downloading at the same time.

One way to see what happens with Chrome is to go to your web page and go to the Network tab in Chrome Devtools, and then refresh the page. It will show you information about when each item is loaded and how long this item is taken to receive from the server.

Depending on which image you are loading and using, there are several other options.

1) If the file size is large and too long to download, find out how to reduce the file size.

2) If you have control over the page from which the user is navigating, you can pre-select the image for the cache on the previous page.

3) You can also try using HTML preloading in addition to CSS. HTML preloading, in my opinion, is only supported by Chrome at the moment, so it might be perfect for this scenario. Add the following to your html head.

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

Did a test with chrome, it started the image upload. The blinking is related to the placement of the image that I think. To understand this, take a look at this test.

Test with a very large 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; } 
0
source

IMHO, this is not preloading. This is just a download, and you use the trick to display the correct image when you hover.

If you really want to preload or, as I understand it, you need β€œyou want the image to be there when you try to hover a button”, then you have different options:

  • proactive:

<link rel="prefetch" href="image1.svg"> <link rel="prefetch" href="image2.svg">

The good thing to add for this is that "there are no restrictions on the same origin for prefetching links."

  • preload:

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

With "preload" resources must be loaded, while this does not always happen with prefetching.

Preload is supported by Chrome, Opera, Android and some others, but Firefox and others. More here

These methods are described in more detail at css-tricks.com

Hope this helps you.

0
source

If you do not want download gaps, you can use a sprite image, or you can set the background image as a base64 encoded image. In this case, the images are always loaded when loading the css file.

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

Here you can convert your svg images to base64: http://b64.io

0
source

I recently used this for the back to top button on my blog http://anggit.com . Will this work for you?

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> 
0
source

Source: https://habr.com/ru/post/1266073/


All Articles