Create a unique Gallery by using z-index and jQuery

Wednesday, April 7, 2010

In this tutorial we want to create a unique picture gallery utilizing the CSS property z-index. In our example we have the appearance of a pile of pictures, on the next action we put the first picture on the last position and on the previous action we get the picture from the last position to the first. All done just by altering the z-index, of course with a animation to underline the imagination to have a pile of pictures.

Preparing the xHTML, CSS and Pictures

We have the wrapping container gallery, a container pictures for the pictures and two controls prev and next for swapping the pictures.

We can add as many pictures as we want because our script will pick them up dynamically.

If the class names of the DIV’s don’t look fimilar to you, they are from the 960 Grid System and just there to positioning the blocks. They don’t affect the jQuery code or the functionality of our gallery in any way.

CSS


/* relevant for the tutorial - start */
  # gallery { position: relative; }
  # pictures { position: relative; height: 408px; }
  # pictures img { position: absolute; top: 0; left: 0; }
  #prev, # next { margin-top: 30px; text-align: center; font-size: 2.0em; }
/* relevant for the tutorial - end */

The pictures container has relative position (under the heading) and a height of one picture. The img’s inside of the pictures container have absolute position. As they are all have a top and left of zero they overlap each other. The last picture (5) in the markup is on top, and the first (1) is on last position.

Pictures Container - Img positioned absolute (Top 0 - Left 0)

Pictures

In the example we use PNG’s, they all are transparent and have the same height and width. To create the effect of a pile of pictures each picture has a smooth drop-shadow and is gently rotated in different directions. I did that manually with Photoshop. If you want to do it programmatically then server side Image Magick may help or you have a look at https://developer.mozilla.org/en/Canvas_tutorial">Canvas (which is pretty fun by the way!).

The principle of changing z-index

The z-index will represent the position of a picture, 1 is the last position and 5 (since we have 5 example pictures) is the top position.

In the next picture action we want to put the first picture to the last postion, means set z-index to 1. All other pictures’ z-index need to be increased by one. Former second picture (4) will become the top picture and so on.

In the previous picture action we want to put the last picture, means z-index 1, to the first position 5. All other pictures’ z-index need to be decreased by one. Former top picture (5) will be put on position 4 and so on.

The Code


$(document).ready(function() { //perform actions when DOM is ready
  var z = 0; //for setting the initial z-index's
  var inAnimation = false; //flag for testing if we are in a animation
  
  $('#pictures img').each(function() { //set the initial z-index's
    z++; //at the end we have the highest z-index value stored in the z variable
    $(this).css('z-index', z); //apply increased z-index to <img />
  });

  function swapFirstLast(isFirst) {
    if(inAnimation) return false; //if already swapping pictures just return
    else inAnimation = true; //set the flag that we process a image
    
    var processZindex, direction, newZindex, inDeCrease; //change for previous or next image
    
    if(isFirst) { processZindex = z; direction = '-'; newZindex = 1; inDeCrease = 1; } //set variables for "next" action
    else { processZindex = 1; direction = ''; newZindex = z; inDeCrease = -1; } //set variables for "previous" action
    
    $('#pictures img').each(function() { //process each image
      if($(this).css('z-index') == processZindex) { //if its the image we need to process
        $(this).animate({ 'top' : direction + $(this).height() + 'px' }, 'slow', function() { //animate the img above/under the gallery (assuming all pictures are equal height)
          $(this).css('z-index', newZindex) //set new z-index
            .animate({ 'top' : '0' }, 'slow', function() { //animate the image back to its original position
              inAnimation = false; //reset the flag
            });
        });
      } else { //not the image we need to process, only in/de-crease z-index
        $(this).animate({ 'top' : '0' }, 'slow', function() { //make sure to wait swapping the z-index when image is above/under the gallery
          $(this).css('z-index', parseInt($(this).css('z-index')) + inDeCrease); //in/de-crease the z-index by one
        });
      }
    });
    
    return false; //don't follow the clicked link
  }
  
  $('#next a').click(function() {
    return swapFirstLast(true); //swap first image to last position
  });
  
  $('#prev a').click(function() {
    return swapFirstLast(false); //swap last image to first position
  });
});

Let’s break that small script into pieces of interest.


$('#pictures img').each(function() { //set the initial z-index's
  z++; //at the end we have the highest z-index value stored in the z variable
  $(this).css('z-index', z); //apply increased z-index to <img />
});

We haven’t set the initial z-index in the markup nor the CSS. To have a starting point we set the z-index’s via jQuery. The order is just as in the markup. After finishing looping through all img in the pictures container we also have the number of pictures and highest z-index value in the variable z.


function swapFirstLast(isFirst) {

We use the same function for the previous and next action as they are doing basically the same thing.


 if (inAnimation) return false; //if already swapping pictures just return
  else inAnimation = true; //set the flag that we process a image

We only want to process one picture at a time. The inAnimation flag determines if we are in a process. If so we just return to the caller without doing anything, if not we set the flag and go on with the picture swapping.


var processZindex, direction, newZindex, inDeCrease; //change for previous or next image
if (isFirst) { processZindex = z; direction = '-'; newZindex = 1; inDeCrease = 1; } //set variables for "next" action
  else { processZindex = 1; direction = ''; newZindex = z; inDeCrease = -1; } //set variables for "previous" action

As we use one function for two processes we need to set some necessary variables. processZindex is the position we need to process, either the first position for the next picture or the last position for the previous picture. The direction is where a picture will animate while swapping, either above or under (-) the pile of pictures. The newZindex will be set to the picture we process, 1 for the last position and the highest z-index for the first position. Last but not least the variable inDeCrease tells if the rest of the pictures’ z-index will be increased (+1 position) or decreased (-1 position) by one.


$('#pictures img').each(function() { //process each image

We loop through all images to check the z-index and alter it.


if ($(this).css('z-index') == processZindex) { //if its the image we need to process
  $(this).animate({ 'top' : direction + $(this).height() + 'px' }, 'slow', function() { //animate the img above/under the gallery (assuming all pictures are equal height)
    $(this).css('z-index', newZindex) //set new z-index
    .animate({ 'top' : '0' }, 'slow', function() { //animate the image back to its original position
    inAnimation = false; //reset the flag
  });
});
}

We check if it’s the image we need to process (either first or last position). If so we go on and animate the picture either above or under the rest of the pile of pictures. When finished with this we set the new z-index to the picture and animate it back in position. When finished and the picture is back in place we release the inAnimation flag.


else { //not the image we need to process, only in/de-crease z-index
  $(this).animate({ 'top' : '0' }, 'slow', function() { //make sure to wait swapping the z-index when image is above/under the gallery
    $(this).css('z-index', parseInt($(this).css('z-index')) + inDeCrease); //in/de-crease the z-index by one
  });
}

Here we bind the click event to the prev and next controls. We return the return value of our function which is always false. Returning false from that click event means we don’t follow the clicked link.

Conclusion

We created a nice looking gallery with just a few lines of code. Of course it could be extended with other features (randomness is pretty kewl: random picture control, slightly random positions each time…) but you get the idea of how to combine a CSS property and the power of jQuery. Feel free to change the code to your needs and be so kind to share it with us in the comments if you like. Every other comment is welcome as well.

Check out the follow up tutorial: Enhancing the z-index Gallery with a preloader .

Comments

Add new comment

Filtered HTML

  • Web page addresses and e-mail addresses turn into links automatically.
  • Allowed HTML tags: <a> <em> <strong> <cite> <blockquote> <code> <ul> <ol> <li> <dl> <dt> <dd>
  • Lines and paragraphs break automatically.

Plain text

  • No HTML tags allowed.
  • Web page addresses and e-mail addresses turn into links automatically.
  • Lines and paragraphs break automatically.
CAPTCHA
This question is for testing whether or not you are a human visitor and to prevent automated spam submissions.
Target Image