How To: Make a CSS background slideshow with jQuery

If jQuery has one strength, it’s the library’s fantastic ability to manipulate HTML objects. Built into the library are easy to use methods for moving objects, adjusting CSS and tag attributes, changing visibility of anything on the page, and many more. To sweeten the deal, jQuery includes animation effects that allow you to transition any object from one state to another in an aesthetic way that only takes a line or two of code.

With these ideas in mind, it’s a small wonder that many jQuery plugins were developed with the intention of easily introducing pretty slideshows to display and rotate series of images. However, if you look around long enough, you’ll be facing a frustrating truth—almost none of these slideshow plugins utilize the idea of rotating CSS backgrounds.

Right now you may be telling yourself, “Self, using rotating CSS backgrounds instead of image tags for a jQuery slideshow is a bad idea.” Well, surprise, this article is a dream within a dream within a dream to convince you of the opposite. When you wake up, you’ll have a changed mind, and better yet, you’ll think it was your idea.

Best practices in HTML, CSS, and Javascript

Let’s have an honest discussion about HTML markup and Javascript. As CSS became a dominant force in shaping the appearance of valid HTML in the 2004 and on, it became more important to structure markup in a meaningful way. Using tables for layout has gone the way of the dinosaurs, DIV overload is now taboo, and designers are utilizing more intelligent information structure in their markup. Somewhere in all this sanity, jQuery has made us a little bit crazy.

“Look how easy it easy to create an image slider for my page’s mast head!”

“But Brian, isn’t it foolish to make a mast head’s appearance reliant on an image tag rather than CSS?”

“Shut up, Self, just look at these animation effects. It’s so easy!”

“But Brian, what if you have 10 different images for a single mast head and jQuery doesn’t load properly or the user has Javascript disabled? Your page is going to look really funny with 10 versions of your mast head all displayed at the same time.”

“…screw those users…”

“This is not good practice, Brian.”

“But… but…”


You get the idea. It’s not a good idea to use an image tag slider unless you’re looking for an alternative way of displaying structured content, such as a photo gallery. However, many designers use these convenient image sliders to display graphics better suited for CSS background use. Slackers.

Fear not, you can have your cake and eat it, too. All you need is jQuery and a bit of know-how. I’m here to provide the know-how, good buddy. Let’s do this—high five!

Creating an CSS background slider with jQuery

Step 1: Markup

We’ll start with the HTML markup and CSS. Our example will be a typical mast head that is of a fixed width and height in the body of the page:

As always, we’ll include the jQuery library and provide a space for our Javascript code in the head of the page:

The line of code $(document).ready(function(){}) is a way of telling your page to execute commands after the page has finished loading. Our script will go inside, just to be sure that our code doesn’t try to manipulate HTML objects that have not yet loaded.

Step 2: Preloading Images

One pitfall of dynamic CSS backgrounds is that when a background image is changed, the user will notice a ‘flicker’ as the new background is loaded on the page. We can avoid unintended visual discrepancies by preloading the images before the background-changing code that is executed.

var imgArr = new Array( // relative paths of images

var preloadArr = new Array();
var i;

/* preload images */
for(i=0; i < imgArr.length; i++){
 preloadArr[i] = new Image();
 preloadArr[i].src = imgArr[i];

Let’s break it down. First, we create an array that holds the relative paths to each image file that we want to include in our rotation. Next, we create another array which will hold Image objects. A Javascript Image object is a symbol of an HTML image element, and once you declare its source, it is cached by the browser. We can then create a loop that goes through our ‘relative path’ array and creates an Image object representing each image we want in our rotation. The source is assigned for each Image object, and viola, our CSS background images are preloaded and cached.

Step 3: Dynamic CSS changes and animation

All that’s left is to take our preloaded CSS background images and rotate them one at a time over a set interval. This can be accomplished with a small amount of code:

var currImg = 1;
var intID = setInterval(changeImg, 6000);

/* image rotator */
function changeImg(){
 $('#mast-head').animate({opacity: 0}, 1000, function(){
 $(this).css('background','url(' + preloadArr[currImg++%preloadArr.length].src +') top center no-repeat');
 }).animate({opacity: 1}, 1000);

There isn’t a lot of code, but there is a lot going on here. First, we set a variable that will map which image in the ‘preloaded’ array is being displayed. Next, we set the interval at which our changeImg() function is executed. Remember, Javascript measures time in milliseconds, so our argument of 6000 is equal to 6 seconds.

Finally, we create the changeImg() function that will change the CSS background image of the element we dictate while animating the process.  The logic is to use jQuery’s animate() method to transition from one CSS state to another over a set amount of time. In our case, we’re changing the opacity to 0 over a 1 second period. Then, we change the background image of the #mast-head element with jQuery’s css() function and a bit of fancy array element selection. At the end, we again use animate() to bring the element’s opacity back to 1. Essentially—fade out, change background, fade in. Neato!

Here’s how your final script will look:

True to form, this jQuery demo has a lot of things happening in a small amount of space.  Use this portable little script for any number of projects, and remember, only use an image tag slider if it makes sense to do so! In many cases, dynamic CSS background changes are best practice. Check out this script in action.

Until next time, amigos, happy programming.


  • Henri Lindeberg

    Is it possible to fade the new background on top of the old one, so there will not be the white background showing in the middle of the change of the pictures?

    • Francisco M. Marzoa Alonso

      In theory you can use double buffering, using two divs at same position and with same dimmensions, and copying the last showed image in the background one before doing the fade animation for the new one.

      I have plans of doing that for my site, but not before I complete other priorities.


  • Chris

    Hi – this is spot on! Just wondering how I could add to it so the iniital background image faded in on page load?

    Many thanks

  • Riccardo

    Thanks for the guide, Brian, much appreciated!

  • Kris Van Houten

    Great tutorial, works great. One question, is there a way to make the background images link to pages?

  • Jan

    I use the script in an Drupal-Template. jQuery is loaded. The script is loaded.
    For $(‘#masthead’) is used $(‘#contentwrap’) for my DIV with fading background-image.
    The paths to the background-images in the script are correct.

    But there is no sliding background.

    Can i give you some more information so that you can tell me something about the failure?

    Thanks for reading that!

  • BostonianAdam

    Thanks for posting this, it helped me with a project.

  • CaduceusWebs DocsAccount

      I am having trouble getting this to work.  Can anyone offer some advice.  I’m going to paste 1) my html/cfm code;  2) my css file code , 3) screen shot of my file structure.  test.cfm is under the root.    Here is a TEST page that shows it not working.  It seems to only load the 2.jpg which is from the CSS file:


    Untitled Document

                    var imgArr = new Array( // relative paths of images
                    var preloadArr = new Array();
                    var i;
                    /* preload images */
                    for(i=0; i < imgArr.length; i++){
                        preloadArr[i] = new Image();
                        preloadArr[i].src = imgArr[i];
                    var currImg = 1;
                    var intID = setInterval(changeImg, 6000);
                    function changeImg(){
                        $('#masthead').animate({opacity: 0}, 1000, function(){
                            $(this).css('background','url(' + preloadArr[currImg++%preloadArr.length].src +') ');
                        }).animate({opacity: 1}, 1000);



    #masthead {width: 950px; height: 350px; background:url(../../accommodations/rotator/2.jpg); border: black solid 1px}


  • paul

    Is there any advantage to placing the jquery on the page as opposed to putting it in a plug-in? Seems like it would be cleaner on the page when there are multiple jquery plugins on the same page. I tried to put it in an external file but failed so I thought I would ask.

  • Francisco M. Marzoa Alonso

    I’m facing problems with this slider and LightBox javascript gallery than I’m using in the same site. When I put this script rel link before lightbox ones, this slider does not work anymore, and viceversa.

    The problem seems to occur when scripts are initialized. It seems like the last executed overrides the initialization of the other put before.

    I think this could be solved just checking if there’s yet an $(document).ready function prepare before changing it, so the first one may be called within the slider initialization code before doing nothing more.

    But… HOW?

    Thanks a lot in advance,

  • Scott Crumpler

    Dude, I just KNEW somebody had to have figured out how to do this.  So many times we use jQuery sliders when we really just want them as a design element and not as a piece of content unto themselves, and THIS METHOD makes so much more sense for that.  Trying it out now!

  • James

    A nice approach, thanks. I had a similar requirement in a project and used the Cycle plugin to swap divs with different background images. It works fine, but somehow your approach seems more elegant. However, an advantage my approach has is that the new background fades over the old one. I  can also trigger the change with a click on a ‘next’ button and go backwards with ‘previous’ button.

    Any thoughts about how to modify your script to do the same?

    • Nicky Lenaers

      How to make it work without having the content fade as well? I use my ‘html’ tag for the slideshow, but when the images fade, the content also fades. Can anyone help me?

  • Baga

    Thanks for the excellent tutorial. Any idea on how can randomize the background images order?

    • Silviu Șamșodan

      var x = Math.floor((Math.random() * 6) + 1);


      background: “#161415 url(./images/slide/img” + x + “.jpg) no-repeat bottom”


  • Duz_Machines

    You have some well placed typos in there,  Thanks for the code

  • Josh Read

    Would it be possible to have a anywhere on the page so a viewer could quickly go to a particular slide? 

  • Frankytap

    How can i do this for the BODY ?

    • rachelbain

      i hope you figured this out, but you just change ‘#masthead’ on line 26 to ‘body’

  • Fernando

    The script is wonderful, but as I’m not very savvy, would you please make these files (html, js, css) and provide them to download? I mean an actual and working files; becuase I had some difficulties to create files and load them to a working mood and was not successful.
    Thank you in advance.

  • Candyce

    This is an awesome script. Each of my background graphics has to link to individual pages. What do I need to do to add links to the background graphics?

  • apprentice

    This is terrific. Any way to include different links for each image as they fade in? Thanks.

  • Mike

    Anyone know how to keep the fade from affecting child elements? Specifically, I have a couple of divs with text and images within the header div that changes background. I’d like my logo and menu divs to remain visible throughout the fade.

  • Komang Sudiartha

    Great scripts,……..
    if you can add some ‘image title’ when mouse come into each image. it will make more usefull. Thanks Komang

  • tinkumax
  • Marcelo

    Sir… u r a genius! Thank u so much for posting this tutorial here. It is so freaking hard to find a slideshow based on CSS background images nowadays, and I really can’t understand why. As if we would never find ourselves in a situation where image tags aren’t suitable. Sometimes they just don’t suit the project, and other alternatives of slideshows should be there available as well. I wish I could contribute to the community and develop/post an alternative myself… but I’m just a designer :p
    Anyhow… thanks once again.

  • rachelbain

    this is amazing! thanks so much for it, it was exactly what i needed (instead of the janky jquery plugins i was working with before). simple, lightweight, perfect. thanks!

  • Barb

    Does anyone know how to add code to the CSS that scales the slide images to fit the browser window? I could do it if the img tags were in the HTML, but they aren’t and I’d like to keep it that way if possible – would appreciate any tips on how to achieve the scaling since obviously on different screen resolutions the slideshow will look awful if I use a fixed size image! Thanks in advance!

  • Justin

    Has anyone figured out how to add links to these background images? I have seen multiple questions about it but know real answers… Any help is greatly appreciated.


  • Mens Underwear

    Great thanks for the tutorial

  • cha

    i love this! very simple! thank you!!!!!

  • Bella

    I am also getting my child divs with the text fading along with the background. Sorry, I couldn’t find the answer. Could anyone help?

    • Silviu Șamșodan

      this is how i use it,hope that will help you:

      var cnt = Math.floor(Math.random() * 6);
      ‘background-image': ‘url(./images/slide/img’ + cnt + ‘.jpg)’,

      var arr = [1, 2, 3, 4, 5, 6];
      var bgrotater = setInterval(function() {
      ‘background-image': ‘url(./images/slide/img’ + arr[cnt++] + ‘.jpg)’,
      ‘-webkit-transition': ‘background 2s ease’,
      ‘-moz-transition': ‘background 2s ease’,
      ‘-o-transition': ‘background 2s ease’,
      ‘transition': ‘background 2s ease’

      if (cnt == 6) cnt = 0;

      }, 10000);

  • Rosa Bassó

    Thanks a lot Brian!! you are my savior for this project:

  • bespired

    ” or the user has Javascript disabled? ”


    But they do have internet, right?
    Why would I want visitors that don’t let them track themselfs on my page?
    Why would I care how they see my page if they don’t care about my profits?

  • Dale Brumbaugh

    In this portion of the code:
    $(this).css(‘background’,’url(‘ + preloadArr[currImg++%preloadArr.length].src +’) top center no-repeat’);
    I’m having difficulty making the images behave as I’d like such as setting the size and other background attributes.
    Can someone assist with the syntax or point me to a good example please? The syntax at W3 seems slightly different and I haven’t gotten that to work.