Thursday 9 September 2010

How To Create A Website With Changing & Fading Background Images

So a client asked me to create a website which used changing & fading background images, and I said that sounded fine and I would check out how it worked, and then I looked it up on t'internet, and no one seemed to know how to do it.  Which surprised me because I'm sure I've seen it done, but maybe they used Flash or something.

So, not be be defeated (even when I read a thing that said it can't be done), I set myself to it, and now it works, which is rather marvellous.  I gave myself a small round of applause.  Then I figured that I should share it, because some people might want to do it but then give up when they read that it's awkward to do.

And so I present:

How To Create A Website With Changing & Fading Background Images
As ever, I deny all responsibility for this going wrong, if you try it and it does.

What we are trying to do:  the website should have a background image which fills the screen.  When the user scrolls, the background should remain fixed in place and the page content should scroll.  Every now and then, the background image should fade into another one.  This is to be achieved using HTML, CSS, Javascript and PHP, as required.

Caveats: this is basically not going to work on IE6, because it just doesn't like these things.  For IE6, just use a fixed background.  The fading effect will be ignored.  Anything below IE6, you probably have no chance.

The problems: having a rotating background image is not hard.  It just involves some css and javascript.  Fixing it in place is also fine.  The problem arises when you want to fade the background, because you can't do that without fading all the child elements... in other words, your page content will fade too.  So, we have to have 2 layers, one with the fading background, and one with the content.  But also, you can't fade one image into another if they're both in the background.  And also as well, sometimes the extra layer gets in the way and all your content moves to after the image.

But do not despair, for it can all be fixed, and here's how:

Step 1: The HTML
The basic idea is that we set 3 layers.  The top one is the page content, which moves when we scroll.  The middle one is the background image.  The lowest layer is the new image, which we fade to.  When the fade is complete, the middle layer gets this new image as well, and the background then gets the next one.  And so on.
Thus we have (I've done the opening pointy brackets the wrong way round, otherwise your browser won't show it):

>body>
    >div id="opacity-background">
       >div id="opacity-layer">
       >/div>
    >/div>
    >div id="mainBody"> Your main page content (header, navigation etc.) goes here
    >/div>
>/body>

'opacity-background' and 'opacity-layer' will handle the images.  If you have an existing site, you can just put a 'mainBody' wrapper round the current content, and then add these 2 divs above it.

Step 2: The CSS
Your CSS should contain the following:

body {
 margin: 0;
 padding: 0;
 position: relative;
}
#opacity-background {
  margin-top: 0;
  width: 1700px;
  height: 1100px;
  z-index: 0;
  position: fixed;
  background-image: url(../img/backgrounds/background1.jpg);
  background-position: top left;
  background-repeat: no-repeat;
  background-attachment: fixed;
}
#opacity-layer {
  margin-top: 0;
  width: 1700px;
  height: 1100px;
  z-index: 0;
  position: fixed;
  background-image: url(../img/backgrounds/background1.jpg);
  background-position: top left;
  background-repeat: no-repeat;
  background-attachment: fixed;
}
#mainBody {
  position: absolute;
  margin-top: 0;
  z-index: 1;
}

Obviously the width and height of the image should be set to whatever size your image is.  And also the background-image url for opacity-background should be set to your own value.  Put this somewhere in your CSS file.

The Javascript
And finally, the javascript.  I used mootools for the fading effect, but you could code it yourself.  I considered this, because I was scared that I wouldn't understand mootools, but actually it's very very easy.  You just get the code (we will come to this presently) and then put it in a file and link to it.

So, let's assume you have a folder called 'scripts', which your javascript files (if you have any) are in.  So you go get mootools, which will give you a file called mootools.js, and you put it in 'scripts', and the in the head section of your page you put (again, I have swapped the pointy opening brackets so that this shows up in your browser):


>script language="javascript" src="./scripts/scmootools.js"> >/script>


so that's it all linked in and everything.  You don't have to have a folder called scripts.  You can just put it in the same place as your head file.

Now you need to add your own bit of javascript. I guess you could put this in an external file as well, but I didn't (I apologise that this is all jumbled up - the line breaks have not, as we say, propagated).


 
  >script type="text/javascript">
 
   var bgImages = new Array();
   bgImages[0] = '../img/backgrounds/background1.jpg';
   bgImages[1] = '../img/backgrounds/background2.jpg';
   bgImages[2] = '../img/backgrounds/background3.jpg';
   bgImages[3] = '../img/backgrounds/background4.jpg';
   var inc=-1;
 
   function backgroundChange() {
    inc++;
    if (inc==4) inc=0;
    // Set background to new image
    var bgDiv = $('opacity-background');
    bgDiv.setStyle('background-image','url(' + bgImages[inc] + ')');
    // Set up fade
    var m = $('opacity-layer');
    var fx = new Fx.Tween(m,{
        duration: 1500,
        onComplete: function(){
                // After fade, show new image on this layer
                m.setStyle('background-image','url(' + bgImages[inc] + ')');
                m.fade('in');
       }
    });
    // Fade out current background
    fx.start('opacity',1,0);
   }
  
   // Navigation sliders and fade effects
   window.addEvent('domready', function(){
    // Add fade effect to all items in navigation menu
    var menuLinks = $$('a').filter(
                           function(item, index){
                            if(item.className == 'toplevelLink') return true; // Top level links
                            if(item.className == 'loneLink') return true; // Top level links
                            if(item.className == 'menu_sub') return true; // Submenu links
                            return false;
                           });
    menuLinks.each(
     function(el,index){
      // Set up morph
      var original = el.getStyle('color');
      var morph = new Fx.Morph(el, { 'duration':'500', link:'cancel'});
      // Attach event handlers
      el.addEvents(
       {
        'mouseenter' : function() { morph.start({'color':'#999999'})},
        'mouseleave' : function() { morph.start({'color':original})}
       }
      );
     }
    );
    // Get top level menus; hide submenus
    $$('a[class=toplevelLink]').each(
     function(el,index){
      // Sliding menus
      var submenu = el.parentNode.getElementsByTagName('ul')[0]; // get sub menu
      var submenuSlide = new Fx.Slide(submenu); // turn submenu into slider
      if(submenu.className != 'this') { // hide submenu for now, unless a page from it is currently shown
       submenuSlide.hide();
      }
      // Attach event handlers
      el.addEvents(
       {'click': function(e){
                     var submenu = el.parentNode.getElementsByTagName('ul')[0]; // get sub menu
                     var submenuSlide = new Fx.Slide(submenu); // turn submenu into slider
                     var thisid = el.id;
                     // Close all other submenus
                     var otherMenus = $$('a').filter(
                           function(item, index){
                            if(item.className != 'toplevelLink') return false;
                            if(item.id != thisid) return true; // Other menus
                            return false;
                           });
                     otherMenus.each(
                             function(el,index){
                               // Set up slide on submenu
                               var slide = new Fx.Slide(el.parentNode.getElementsByTagName('ul')[0]);
                               slide.hide();
                           });
                     // Show or hide this menu, as appropriate
                     submenuSlide.toggle();
                     e.stop();
                 }
       }
      );
     }
    );
    backgroundChange();
   });
   window.addEvent('load', function(){
    var pic = new Array();
    for(var ii=0; ii
     pic[ii]= new Image(100,25);
     pic[ii].src=bgImages[ii];
    }
    setInterval('backgroundChange()', 5000);
   });
  >/script>


So in the head section of your page, after the bit where you put the link to mootools, put the following:

You can play around with this a bit.  Make sure the paths to the images are right.

Basically that's all there is to it.

Appendix: How to get Mootools
I'm always scared of new things, because I'm always certain they won't work, but mooTools is very easy and lets you add lots of nice effects to your site.  It doesn't come with a lot in the way of examples, but it's not hard to figure out.

To get mooTools (it's free, by the way), go to http://mootools.net/download and click one of the links in the first section (I went for the uncompressed one, but as long as you can uncompress them, the others are fine).  That gets you mootools.js.

3 comments:

Virtual Methodist said...

In a previous era you would have been burned as a witch! ie back in the day of IE3!

Unknown said...

This article providing perfect information about Create A Website With Changing & Fading Background Images.Really useful things to beginner of web designer.
Web Design Company Bangalore

Anonymous said...

Thank you for this post! I am going to be implementing a design soon that uses a large background. This should work perfectly.
digital marketing agency, online marketing company