Animated background image with jQuery

by Jean. 86 Comments -

If you’re used to work with the jQuery library, there’s no doubt that you know how powerful it is. In this tutorial, we are going to create a basic web page layout which includes a super cool animated background image, using jQuery.

Getting ready

In this tutorial, we are going to create a simple layout for a website, which includes a very cool animated background. Here is how the final result will look:

As you can see, in this example I have used the Twitter background clouds, which look really nice.
This tutorial has been inspired by the one called How To Build an Animated Header in jQuery that I definitely recommend you go check out.

Let’s do it

1. The first step of this tutorial is to download our background image. I have used this one from Twitter, but of course feel free to use any other image you’d like.

2. Once finished, let’s create a a file called index.html. In order to get started with the basic HTML structure, paste the following code in your file:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "">
		<meta http-equiv="Content-type" content="text/html; charset=utf-8" />
		<title>Animated background Image</title>


3. Now, let’s define our document structure. Since we want to do a simple layout, we’ll only need to create a header and content area. Paste the following within the <body> and </body> tags:

<div id="container">
	<div id="header">
		<h1>Animated Background Image</h1>
	</div><!-- #header -->

	<div id="content">
		<!-- Your content will go here -->
	</div><!-- #content -->
</div><!-- #container -->

4. Well done! We already have our XHTML. Now, what we have to do is obviously use some CSS and give style to our document.
To do so, copy the code below and paste it within the <head> and <head> tags of the index.html file.

<style type="text/css" media="screen">
		background-color: #C0DEED;

		background: #8EC1DA url(bg-clouds.png) repeat-y scroll left top;

	#header h1{
		font-family: "Myriad Pro", Helvetica, Arial, sans-serif;

		margin:25px auto 0 auto;

5. At this point, you can save your work and take a look at the index.html page using your web browser. If everything is ok, your index.html page should look like the screenshot above, with fixed clouds, of course.

6. Now, it’s time to give life to the layout by using the power of jQuery. As you probably guessed it, what we have to do right now is include the library. Since Google hosts a version that you can use, there’s definitely no need to download a copy. Just use the one from Google.

To do so, paste the following line of code in your index.html file, after the closing </body> tag:

<script src="" type="text/javascript" charset="utf-8"></script>

7. Now that jQuery has been loaded, we can code a function to animate the background. Copy the code below and paste it on your index.html file, just after the line where you imported jQuery into the file.

<script type="text/javascript" charset="utf-8">
	var scrollSpeed = 70;
	var step = 1;
	var current = 0;
	var imageWidth = 2247;
	var headerWidth = 800;		

	var restartPosition = -(imageWidth - headerWidth);

	function scrollBg(){
		current -= step;
		if (current == restartPosition){
			current = 0;

		$('#header').css("background-position",current+"px 0");

	var init = setInterval("scrollBg()", scrollSpeed);

There’s nothing really hard with that code. First, we declare a set of variables to control the animation (image width, scroll speed, etc). Then, we created a function to automatically move the background. The most tricky part is to calculate when we need to reset the position. If you have a better idea about doing it, let me know in a comment! ;)

Demo & Download

I hope you enjoyed this tutorial and helps you to create very nice websites. If you want, you can see a Demo of this code, or you can Download the source files.

Comments (86) - Leave yours

  1. Wes Bos said:

    Great tutorial Jean, this is just another step towards flash dying.

    The image doesnt get added until there is enough space for it so there is a gap every 20 seconds or so. See this screenshot:

    Firefox 3.5

  2. John said:

    Wes – I fixed it with changing var imageWidth = 2247; to var imageWidth = 1700; but I assume you could change the headerWidth also.

    Does this have increased CPU usage because I tested it and it revved up my processor pretty good. Maybe it’s just me?

  3. Bruno said:

    Great, but is there very usefull to load jquery just for this animation?

    It’s really easy to use default function and speed up the execution time (while not using jquery somewhere else ofc) of the script by changing line 73 into :
    document.getElementById(‘header’).style.backgroundPosition = current+’px 0′;

    If you’re using Prototype or Mootools :
    $(‘header’).setStyle(“background-position”,current+”px 0″);

  4. Anna said:

    Great tutorial!

    Currentry I’m working on the same approach for one of the project – and I’ve met at least two small problems, that was not covered in your tutorial (as for myself I have not found any optimal solution for them yet)…

    1. When the cycle ends end animation restarts there is visible jump in image… When we dealing with vertiacal moving that easily could be fixed with the same pixel-set in the beginnig and in the end of animation that equal to the header height, but in the horizontal case it does not work because we don’t now the width of user’s window in this moment and this width is different for different users

    2. In your case restart position is calculated assuming that the header width is 800px, but if user has screen resolution more than 800*600 – this put you in a trouble because the user will see the end of the picture moving on the screen before the animation restarts… so there we also meet the question about user’s screen width

    probably further discussions will reveal some solutions :)
    anyway thank you a lot for sharing this code :)

  5. InTRUEdeR said:

    “var headerWidth = $(‘html’).width();” will work with any screen resolutions, but headerWidth need to be updated inside script when user resize window.

  6. ORiOn said:

    By the way, you can determinate the screen resolution with: screen.width

    You just need to put it like this: var headerWidth = screen.width;

    There you go! :D

  7. charisma said:

    hi don’t forget to check another inspiration at my web site click product and choose another design and after that choose my type…i have another animation for background just with jquery..i really like it..and i really like your web site name “catswhocode” ,thankyou..

  8. Zack said:

    This is pretty slick, thank you for sharing it.

    To make the animation seamless could you use two exact images that rotate positions?

    For example as image1 is halfway through it’s animation, image2 would append to the end of image1.

    When image2 moves completely into the background space, image1 would append to the end of image2.

  9. Kapil said:

    Thanks alot for the neat trick. I am planning to do something similar with my personal site with some extra parameters. But this one saved me alot of coding time. :)

  10. James M. said:

    Wow, first time I saw an effect like this. I thought things like this are exclusive for flash websites only. I’m definitely exploring this trick. I just might incorporate it in some sites of mine. Thanks a lot.

  11. Pieter said:

    Hmm, nice start but this needs some work.

    At first I would make it go slower, which will make it less distracting. Then second, as mentioned before, it jumps when it reaches the end, so you should get the screen width and work with that value.

    Third, some people say it gets their CPU really pumped up and that’s not what we want right.

    Nice start!

  12. Alex said:

    Here’s my solution for the time being:

    If you open the ‘bg-clouds.png” in Photoshop and tile the clouds to something like the width of 6741pixels and re-save it, it’s only a 100kb image still. Set the “var scrollSpeed = 70;” and you’re all set.

    Now, the kick doesn’t come in for a looooong time ;)

  13. Archetoy said:

    Great tute, and nice code. Would love to see this with multiple depth, like parallax scrolling, so, back mid front.

    Great blog, and thanks for sharing, Digging now =)

  14. chinoke said:

    I just want to say that Cats are really good in writing codes “art of code” after what i read in this website; Gratz

  15. PaulO said:

    Here’s a way to get around the end of image problem:

    1. Use an image that can wrap horizontally.
    2. Add to the background style “repeat-x”.
    3. Update this line of code: “var restartPosition = -(imageWidth);”

    It’s a cool effect, but still trying to figure out if I should use it or not.

  16. Mermaid said:

    Another useful article!
    Jean-Baptiste, your whole blog is really great. Everytime I have a new idea, I keep coming back here and chances are you already covered it with a great tutorial.
    Like this one.

  17. dante said:

    Hey man, awesome tut.
    I tried to modify it so it scrolls vertically, but then IE gives me an error (I don’t care about error itself, but it wont animate in IE) in Jquery.1.4.2.js, whether it’s hosted on google or by me… weird stuff.

    here’s the code:

    var scrollSpeed = 70;
    var step = 1;
    var current = 0;
    var imageHeight = 458;
    var headerHeight = 1000;
    var restartPosition = -(imageHeight – headerHeight);
    function scrollBg(){
    current -= step;
    if (current == restartPosition){
    current = 0;
    var init = setInterval(“scrollBg()”, scrollSpeed);

    please help!! :( (((

    • Seeholzer said:

      I used the vertical image animation and it works:

      /* vertical animation */

      var scrollSpeed = 300;
      var step = 150;
      var current = 0;
      var imageHeight = 1350;
      var headerHeight = 150;

      var restartPosition = -(imageHeight);

      function scrollBg(){
      current -= step;
      if (current == restartPosition){
      current = 0;

      $(‘#animation’).css(“background-position”,”0 “+current+”px”);

      var init = setInterval(“scrollBg()”, scrollSpeed);

  18. dante said:

    OK NVM I did it!11

    I just copied code again and after careful analysis it seems that I had deleted empty space after zero:


    now it’s like:

    $(‘#logo3′).css(“background-position”,”0 “+current+”px”);

    and it works.
    I can’t believe how much SUCK IE contains, but ok.
    sorry for useless posts. :D

    great tut again, btw.

  19. Chuck said:

    Wouldn’t be much easier like this?:

    function scrollBar(){
    $(‘#header’).css(“background-position”,”0px 0px”).animate({backgroundPosition: “-2247px 0px”},4000,”linear”,scrollBar);



  20. Jamie said:

    Another great tutorial. I like the Twitter background. I previewed the demo and it was great. Looking forward to some more tutorials from you.

  21. Le said:

    Hi there,

    Nice code!

    Some changes to continuous move.

    var imageWidth = 2247; // Background image width
    var headerWidth = 1685; // How wide the header is.

    I Hope helped someone


  22. james westgate said:

    Two immediate problems here:

    1. Just use jQuery animation so that your animation fits in with other animations running on the page,

    2. If you do use your own timer, dont pass a string to setInterval, use an anonymous function instead eg

    function() {scrollBg()};

    This will improve performance.

  23. y0y0 said:

    Thanks for the code!

    Quick question: Is there a way to do this without the global variables? I’d rather make them all local and neat.

  24. Mr Gibons said:

    Hey, I am trying to expand the content section so it expands to 100% of the height but, if I do this the box disappears. Any help?

  25. Sotiris Kalathas said:

    A little improvement to your awesome script:

    No need for var headerWidth just use $(“#header”).width() or $(window).width() instead, any will do!

    I also changed the script to scroll the other way!


    var scrollSpeed = 1; // Speed in milliseconds
    var step = -1; // How many pixels to move per step
    var current = 0; // The current pixel row
    var imageWidth = 2247; // Background image width

    //The pixel row where to start a new loop
    var restartPosition = -(imageWidth – $(window).width());

    function scrollBg(){
    //Go to next pixel row.
    current += step;

    //If at the end of the image, then go to the top.
    if (current == restartPosition){

    current = 0;

    //Set the CSS of the header.
    $(‘#header’).css(“background-position”,current+”px 0″);

    //Calls the scrolling function repeatedly
    var init = setInterval(“scrollBg()”, scrollSpeed);

  26. Lucas said:

    I could not make it scroll vertically, even with the examples here posted, do i have to change something in the CSS? please who ever knows, post the full code! thanks!

  27. ArthurD said:

    So many people are confusing the issue with the header repeating. The point of repeat has nothing to do with the actual width of the header, but the point that the pattern repeats. So for example if you have a pattern repeats after 100 pixels then you subtract that from the total width of the background pattern. So if the image width were 2000, then this is what the two values would be:

    var imageWidth = 2000;
    var headerWidth =1900;

    now if your image doesn’t repeat for the entire length of the image then all you would have to do is set the variableas as follows:

    var imageWidth = 2000;
    var headerWidth =0;

    With repeat-x turned on the image will blend seamlessly with it self. Of course there are other methods of achieving what’s being done here, but this is how you get the background to repeat using this code.

  28. dean said:

    somthing missing????????????

    //The pixel row where to start a new loop
    var restartPosition = -(imageWidth – $(window).width());

  29. chris said:

    Very good trick, but not complete.. How do you clear the memory and reset the image on one successful scroll because if you start taskmanager you can see the cpu usage going up and up and up the longer you leave the loop going?

Leave a Reply

Your email address will not be published. Required fields are marked *

Please respect the following rules: No advertising, no spam, no keyword in name field. Thank you!