CSS Throwdown: Preload Images without JavaScript
Clean, easy, effective. You don’t need no stinking JavaScript to preload your images. Nope. Try some tasty CSS and (X)HTML instead! Here’s how to do it with only two easy steps..
Step 1 — Place this in your CSS file:
div#preloaded-images {
position: absolute;
overflow: hidden;
left: -9999px;
top: -9999px;
height: 1px;
width: 1px;
}
Step 2 — Place this at the bottom of your (X)HTML document:
<div id="preloaded-images">
<img src="https://perishablepress.com/image-01.png" width="1" height="1" alt="" />
<img src="https://perishablepress.com/image-02.png" width="1" height="1" alt="" />
<img src="https://perishablepress.com/image-03.png" width="1" height="1" alt="" />
</div>
..and that’s a wrap! All images are preloaded and ready for calling as you please. Completely valid, standards-compliant image preloading via CSS and (X)HTML!!
About the Author
Jeff Starr = Web Developer. Book Author. Secretly Important.
68 responses to “CSS Throwdown: Preload Images without JavaScript”
The drawback is, because the images are technically part of the page, the browser is going to load them… that’s why it’s a preload, right? But it will load them WITH the rest of the page. A Javascript preload usually triggers just after the page is rendered, while the user is looking at the finished page. This will trigger DURING the layout. So it will slow down the initial page load and rendering.
I’m sticking with the Javascript. Besides, it’s like 5 lines of code – that’s LESS than this method.
@Chetter Hummin: I would tend to agree, but until JavaScript is more widely supported than CSS, any JS preloading method is significantly less reliable.
the method is completely wrong. I think you’re forgetting the most basic of CSS/xHTML/JS. HTML is for Presentation, CSS is for Styling and Javascript is for the Behavior.
You’re using CSS to simulate behavior to a page which is wrong. Imagine a screen reader or a search engine trying to crawl this web page…. get it? How would you explain this DIV on a search engine? Also the empty ALTs are so lame! This is so Web -2…
cheers
@Antony: Wow, you certainly seem knowledgeable about the topic of preloading images. Perhaps you would care to enlighten us with a better technique?
@Nic – The images only belong IN the page if they are content. If they are just there to make things pretty then they should be referenced in the external CSS file.
The golden rule is if you turn CSS off does the absence of the image detract from the meaning of the page? If so put the image in the HTML, if not put it in CSS.
@Antony – HTML is for content. It is for the bits that have meaning. CSS is for the styling of the content. Therefore CSS is the for PRESENTATION of the HTML.
@martin white – whilst you’re at it you could combine all the images into one big sprite and go from 28 images to 1.
@everyone – There are lots of reasons to avoid using javascript. Not least of all because that JS should be in a separate file and therefore requires another HTTP connection to fetch it. If you’re already using a CSS file then it doesn’t require another HTTP connection to preload some images with it.
@Jeff Starr: no I don’t. I’m just using a simple JS preloader when I have situations like rollover navigation buttons etc. Your technique is very clever thought it can’t be used because of the nature of xHTML and CSS.
@mjcpk: we’re saying the same thing but you must understand that this method is trying to create ACTIONS and BEHAVIOR on a web page using CSS which is semantically wrong. There is a good reason why JS is there and I can sacrifice one more file request for the shake of image preloading. I’m always using CSS Sprites when it comes to re-usable graphics on my pages so one more file request is not a big deal. For me it matters more the content to have meaning and Web Standards to work on my pages.
@Antony: CSS is used to load images all the time. For example, the
background
property is commonly used for loading and displaying various types of background images. Is this considered behavior? Are you saying that using CSS to load a background image does not qualify as behavior but that using CSS to load a gallery image somehow does qualify as behavior? How can you define loading images as behavior based on how the images are used on the page? Or are you defining CSS image loading as behavior based on whether the images are displayed or not? If so, what about sprites? Sprites are not always seen, so is it semantically correct to use CSS for sprites? CSS is used not only to load and display the sprites, but also to change the position of the sprite images based on certain actions. So does this count as behavior? Maybe we should stop using CSS to display all images because some of them are applied via “behavioral” CSS while others are not? Please help us to understand how to apply semantically sound Web Standards to the proper handling of images via CSS.Nice post! I like it….The images are loaded, but that is because they are in the XHTML code. it also very light and it download very fast . great
Hmmm, well this seems to have got a little out of hand :)
@Antony – Its nice to see you understand the accessibility side of things with the empty images without “alt” tags. Did you know that if an image doesn’t contain an alt tag it doesn’t appear on a screenreader? Alt tags are there to provide an Alternative description for the image in the case where it is important to make sure the person browsing the website can still understand the message of the page IF the image is part of that message. Preloaded images don’t need alt tags. The original image can contain it. Lets think of those people using screenreaders for a moment… I personally wouldnt want to know there was an image call “preloaded image” on the page because it means nothing to my experience of reading the page I’m on. So lets not stick them in places they aren’t needed without thinking about the logic of why we put it there.
Anyway, a-side, Im with @mjcpk on this and personally believe the CSS approach is better because.. well, it works without Javascript, less HTTP requests and the total image sizes are lower (combining 2 images to one is smaller because there arent two image headers involved and it combines pallets).
Thinking of accessibility again, lets not just assume that everyone has Javascript. In the instance of it being disabled, the CSS hover effect is still going to work. CSS has something called “hover” Antony. Its an effect and its been around a long time. Its purpose is to create an “effect” when people do things on the page. It’s so we don’t have to rely on Javascript all the time to do very basic procedures such as mouseover effects. I personally don’t want to have to apply a function to every link on the page OR produce a recursive onload event to apply a hover effect to my elements. That’s why CSS has these little things to help us apply a global effect quickly to the page. What you are saying is that CSS should not have the :hover effect anymore because its producing an action and a behaviour. (looks puzzled).
Oh, and another thing.. preloaded images still load at almost the same time as the page content. Did you know that the header scripts run when the XHTML code is finished loading and NOT the images? This means that whilst images are loading in the body, your javascript is already running too and loading those additional preloaded images. It doesn’t wait until all images in the BODY are finished before it fires.
Finally.. the “nature” of CSS and XHTML is what exactly? The purpose of XHTML is to produce a globally aligned programming structure that we can follow to help us produce sites that work better on a myriad of browsers and devices. CSS is the thing that then paints it.
Javascript should only be used to enhance the experience for those that can use it, the website should NEVER, in any circumstance, rely on it as its primary source of functioning. There should always be a fallback. So the less we use Javascript, the better.
Great method to use, just wanted to say thanks.
For some reason, I can’t get this to work in Firefox 3.5.2. Any ideas?
I just use this method
Create a Div tag at the bottom of your page after your footer
Like so:
After thats doen create a css rule
#preloadimg {
width: 0px;
height: 0px;
display: inline;
background-image: url(images/NAME OF IMAGE HERE);
background-image: url(images/NAME OF IMAGE HERE);
background-image: url(images/NAME OF IMAGE HERE);
etc...
}
this seems to work just fine!