49

On one of my HTML pages there are some large images that are shown when I mouse hover over some links and it takes time to load those images.

I don't want to use JavaScript to preload images. Are there any good solutions?

BinaryButterfly
  • 18,137
  • 13
  • 50
  • 91
Wasim Shaikh
  • 6,880
  • 18
  • 61
  • 88

10 Answers10

73

HTML5 has a new way to do this, by link prefetching.

<link rel="prefetch" href="http://davidwalsh.name/wp-content/themes/walshbook3/images/sprite.png" />

Just add as many link tags as you need in your HTML and you are good to go. Of course, older browsers will not load the content this way.

Note Above code will not work for Apple Safari safari does not support prefetch til now version 12 https://caniuse.com/#search=prefetch

UPDATE

If your server is served with HTTP2, you can also add a Link header in your response a made use of HTTP2 Server Push.

Link: <http://davidwalsh.name/wp-content/themes/walshbook3/images/sprite.png>; rel=preload; as=image;
BinaryButterfly
  • 18,137
  • 13
  • 50
  • 91
Luis Dalmolin
  • 3,416
  • 1
  • 18
  • 24
37

From http://snipplr.com/view/2122/css-image-preloader

A low-tech but useful technique that uses only CSS. After placing the css in your stylesheet, insert this just below the body tag of your page: Whenever the images are referenced throughout your pages they will now be loaded from cache.

#preloadedImages
{
    width: 0px;
    height: 0px;
    display: inline;
    background-image: url(path/to/image1.png);
    background-image: url(path/to/image2.png);
    background-image: url(path/to/image3.png);
    background-image: url(path/to/image4.png);
    background-image: url();

}
Khurram Aziz
  • 1,480
  • 5
  • 15
  • 24
  • Thanks a Lot AZIZ. This is really Good solution for the Preload. Still Hoping for more solutions. Then close the Answer, – Wasim Shaikh May 04 '09 at 13:50
  • 32
    this MOST DEFINITLY does not work. only the last empty url() is parsed. – vsync Dec 07 '11 at 12:33
  • 1
    That doesn't work as @vsync already wrote. But you may put all images in one background property: background-image: url(path/to/image1.png), background-image: url(path/to/image2.png),url(path/to/image3.png), url(path/to/image4.png); – Jokus Mar 08 '18 at 16:33
29

There is no need to preload images. I can't understand why 99% people thinks, that hover effects have to use 2 images. There is no such need, and using 2 images makes it look bad. The only good solution I know is to use CSS for A elements (or easy JS for all other buttons). When button us hovered set background-position to some offset.

a { display:block; width:160px; height:26px; background:url(b_tagsdesc.png); }
a:hover { background-position:0 26px }

That's all, image used you can see below:

alt text
(source: margonem.pl)

Edit: You can also use it other way. Instead of toggling image, you can hide your image. So starting point would be "background-position:0 -100px" and on hover "0 0".

This technique is called CSS sprites - here is good description of it: http://css-tricks.com/css-sprites/

Glorfindel
  • 21,988
  • 13
  • 81
  • 109
Thinker
  • 14,234
  • 9
  • 40
  • 55
  • 1
    I can't stress this out enough. This is the (only) way to go. – Kriem May 04 '09 at 18:17
  • Nice compact sample. Helped me a lot to do it this way. – Marc Jun 21 '12 at 11:10
  • 47
    Sprites are great, but there *are* cases where you need to preload images. – Andrew Hedges Jul 08 '12 at 17:58
  • Sprites work great for abrupt transitions, but fail to fade with gradual transitions. – Timofey Drozhzhin Oct 27 '13 at 04:21
  • 5
    Preloading is also useful for animations. Like an ajax loading image. – Bradmage Jan 04 '14 at 04:13
  • 7
    "There is no need to preload images." This is just rubbish. What if you're timing how long a user views an image? Or you're playing a game and you want all your assets to be loaded up before you render the scene? – Rhys van der Waerden Oct 31 '16 at 03:32
  • There is a slightly faster solution (check my answer below). However, it is a bit more complicated. So, if you are just looking for a simple quick n' dirty way to improve the speed then you should use this way. –  Apr 22 '17 at 00:30
14

A technique I didn't see mentioned here yet, which works great if you don't need to worry about IE6 & 7, is to use the :after pseudo-selector to add your images as content to an element on the page. Code below lifted from this article:

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

The only downside I can see to this compared to using JavaScript to preload the images is that there is no easy way to release them from memory.

Andrew Hedges
  • 21,688
  • 16
  • 67
  • 79
  • 2
    While this _mostly_ works, some browsers (for example Opera) will not download images for display:none elements. http://www.quirksmode.org/css/displayimg.html – Cristian Vrabie Aug 28 '14 at 11:15
  • 1
    You could however include it without display none but position it outside the drawn area: `background-position: -100px -100px;`. – Cristian Vrabie Aug 28 '14 at 11:24
13

You could use a hidden div to put images in. Like so

<html>
<body>
<div style="width:1px; height:1px; visibility:hidden; overflow:hidden">
    <img src="img1.jpg" /><img src="img2.jpg" />
</div>
<div>Some html</div>
</body>
</html>

This only works for images though, ie. if you're trying to do the same for say .swf files there will be problems. Firefox doesn't run the .swf file if it's not visible.

Matti Lyra
  • 12,828
  • 8
  • 49
  • 67
  • 2
    Would you also not need display:none since visibility will still take up space? But I also believe that some browsers don't load hidden images till they are shown. – Darryl Hein May 04 '09 at 09:17
  • 1
    This is really Good Solution , we can also Use position absolute and ; height:0 in CSS, Isnt it? – Wasim Shaikh May 04 '09 at 09:28
  • 1
    If it isn't loaded when hidden, maybe it would help have some "visible" span/div of height 0 with style="background:url(imgx.jpg)"? Just an idea... don't know if it helps or works :p – Svish May 04 '09 at 09:32
4
<link rel="preload" as="image" href="..." />

This works best for me when we want to load image early for CSS (while rel="prefetch" will cause duplicate loading from CSS)

2

If preloading images is what you seek, then performance is what you want. I doubt blocking up the page while the resources load is what you want. SO, just place some prefetching links at the end of the body and add the bogus media to them to make them appear unimportant (so that they get loaded after everything else). Then, add the onload tag to those links, and in that onload will be the code that sets the source of the actual resource in your page. For example, this could even be used in conjunction with dynamic iframes.

Before:

<a onclick="myFrame.style.opacity=1-myFrame.style.opacity;myFrame.src='http://jquery.com/'">
    Click here to toggle it
</a><br />
<iframe id="myFrame" src="" style="opacity: 0"></iframe>

After:

<a onclick="myFrame.style.opacity=1-myFrame.style.opacity">
    Click here to toggle it
</a><br />
<iframe id="myFrame" src="" style="opacity: 0"></iframe>
<link rel="prefetch" href="http://jquery.com/"
      onload="myFrame.src=this.href" media="bogus" />

Notice how the first one (before) freezes up the page and blinks in a quite ugly manner while the second one (after) with the content preloaded doesn't freeze up the page or blink, rather it appears and disappears seamlessly instantly.

2

Reference your images in invisible img tags. while page loading they will downloaded too.

Canavar
  • 47,715
  • 17
  • 91
  • 122
2

As I'm not sure if hidden images are loaded, you'll probably want to use image sprites. Then the entire image is loaded before anything is displayed. You can even put all of your menu items in one image and therefore save a lot of HTTP requests.

Darryl Hein
  • 142,451
  • 95
  • 218
  • 261
1

Can't you add them as an <img /> tag to your page and hide them using css?

Peter
  • 14,221
  • 15
  • 70
  • 110