Lately at my job, our internet connection has slowed down dramatically. This means that every http request over our internet connection is much more noticeable. I often refer back to my own website while at work, to steal some code or see how I did something in the past. One of the things I've noticed with our slow internet connection is my main navigation menu's background-image is really laggy. The image on the drop down which has a value of display: none; would have a 3 second delay before displaying.
Annoyed by the extreme delay in my menu's background-image I started tinkering to solve the problem. My first tool of choice was using the Firefox Live HTTP Headers addon. Using this I could load the page, and then proceed to hover over elements to see if the browser was hitting the server for images or other files. I noticed on my navigation that when I hovered over it, it needed to retrieve my background-image from the server. This made finding a solution much easier.
What CSS Properties Will Do A CSS Image Preload?
The following methods will download the images from the web server upon page load. This assumes the following code which might be some element within your site's template:
<div id="preload"></div>
These Methods Successfully Downloaded The CSS Preload Image Upon Page Load
#preload { background-image: url(image.png); position: absolute; left: -9999px; }
#preload { background-image: url(image.png); visibility: hidden; }
#preload { background-image: url(image.png); background-repeat: no-repeat; background-position: -9999px -9999px; }
I consider the background-repeat: no-repeat; background-position: -9999px -9999px; to be the most practical of these methods
These Methods Did Not Download The CSS Preload Image Upon Page Load
#preload { background-image: url(image.png); display: none; }
#preload:hover { background-image: url(image.png); }
#preload:active { background-image: url(image.png); }
#preload:focus { background-image: url(image.png); }
The browser will not download the images upon page load if the element has a display: none; property (interesting that they will download the image if it's visibility is set to hidden). The browser will also not download images that have a :hover, :active or :focus in it's selector.
CSS Sprites?
Nope, sorry, before you even bother commenting "why not use CSS sprites?" In my situation that was not an option. The element I wanted to preload the image for had :hover for it's parent element and display: none; set, talk about a double whammy CSS sprites only work for elements that are visible on page load. I should digress that I could have bundled these images with some other images in my site's template but semantically they had no useful purpose with any other background-image.
The Solution?
I ended up using the background-repeat: no-repeat; background-position: -9999px -9999px; method. The trick is I needed to place my CSS background-image on some unused element on the page. This is not the best solution for CSS maintainability but it was a necessary evil if I wanted my hidden background-image to load before it was displayed on :hover
How It's Done
I had two elements on my page (in close proximity or parents of my elements). I decided to place these selectors in their own section of my stylesheet so that they would stand out a bit.
#nav { background: url(/files/images/template/menu_bg-trans.png) no-repeat -9999px -9999px; }
#header { background: url(/files/images/template/helper_a_bg-trans.png) no-repeat -9999px -9999px; }
Optimal Solution?
No, not really but It fixed a problem I had. One could also create specific DIVs just for image preloading and absolutely position them outside of the viewport, but that just adds extra markup to the page and isn't really semantically correct. Feel free to leave a comment if you can think of a better way.