Animated CSS3 Photo Stack

Demo Download

In this tutorial, we are going to build an animated photo stack, which will use all kinds of fancy effects to transition between a set of images. The effects are implemented purely using CSS3, which means that they run smoothly on modern browsers and mobile devices. We will also make the photo stack advance automatically, so you can use it as a slideshow.

The HTML

As always, the first step is to present the markup of the example. We are starting with a regular HTML5 document in which we are including a number of CSS/JS files:

index.html

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />

    <title>Animated CSS3 Photo Stack | Tutorialzine Demo</title>

    <!-- CSS Includes -->
    <link href="assets/css/style.css" rel="stylesheet" />
    <link href="assets/css/animate.css" rel="stylesheet" />

</head>
<body>

    <ul id="photos">
        <li><a href="http://www.flickr.com/photos/brockwhittaker/8500935165/"
        style="background-image:url(...)">Landscape 5</a></li>
        <!-- More photos here -->
    </ul>

    <a href="#" class="arrow previous"></a>
    <a href="#" class="arrow next"></a>

    <!-- Libraries -->
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
    <script src="assets/js/script.js"></script>

</body>
</html>

The #photos UL holds the photos that we will be animating. For each photo, I've defined a LI item with an anchor element inside it. The image is set as the background-image property of the link. As you will see in the CSS part, I am using the background-size property to force the image to cover the entire width and height of the link. When adding more photos, keep in mind that because they are positioned absolutely, they will be shown in reverse order (the last photo will be at the top).

In the head section of the document, I am including our main stylesheet and animate.css - the library that gives us those wonderful CSS3 animations. Before the closing body tag, we have the jQuery library and script.js which we will discuss next.

animated-photo-stack.jpg

The JavaScript

To trigger the effects that the animate library gives us, we have to assign a class name to the element with the name of the animation. We will also have to move the animated photo at the bottom of the stack after the animation finishes, so that we can show the next image. Here is what we need to do in order to make this example work:

  • First, we will listen for clicks on the arrows;
  • Then, when a click occurs on the next arrow, we will trigger a randomly chosen CSS animation by assigning a class name to the topmost element of the stack (this is actually the last LI item because of the positioning);
  • After one second, when the animation completes, we will move the animated element before the other LIs with the prependTo jQuery method (this will push it to the bottom of the stack) and remove the classes that we've assigned above.
  • For the previous arrow, we will do nearly the same, with the only difference being that we will take the last image and place it at the top of the stack before triggering the animation.

In addition, I will also add auto-advance functionality like we did in this article. This will turn the example into a cool slideshow that stops the automated transitions when you click one of the arrows.

Here is what the code looks like:

assets/js/script.js

$(function() {

    var exits = ['fadeOut', 'fadeOutDown', 'fadeOutUpBig', 'bounceOut', 'bounceOutDown',
        'hinge', 'bounceOutUp', 'bounceOutLeft', 'rotateOut', 'rotateOutUpLeft',
        'lightSpeedOut', 'rollOut'];

    var entrances = ['fadeIn', 'fadeInDown', 'fadeInRight', 'bounceIn', 'bounceInRight',
            'rotateIn', 'rotateInDownLeft', 'lightSpeedIn', 'rollIn', 'bounceInDown']; 

    var photos = $('#photos'),
        ignoreClicks = false;

    $('.arrow').click(function(e, simulated){
        if(ignoreClicks){

            // If clicks on the arrows should be ignored,
            // stop the event from triggering the rest
            // of the handlers

            e.stopImmediatePropagation();
            return false;
        }

        // Otherwise allow this click to proceed,
        // but raise the ignoreClicks flag

        ignoreClicks = true;

        if(!simulated){
            // Once the user clicks on the arrows,
            // stop the automatic slideshow
            clearInterval(slideshow);
        }
    });

    // Listen for clicks on the next arrow
    $('.arrow.next').click(function(e){

        e.preventDefault();

        // The topmost element
        var elem = $('#photos li:last');

        // Apply a random exit animation
        elem.addClass('animated')
            .addClass( exits[Math.floor(exits.length*Math.random())] );

        setTimeout(function(){

            // Reset the classes
            elem.attr('class','').prependTo(photos);

            // The animation is complate!
            // Allow clicks again:
            ignoreClicks = false;

        },1000);
    });

    // Listen for clicks on the previous arrow
    $('.arrow.previous').click(function(e){

        e.preventDefault();

        // The bottom-most element
        var elem = $('#photos li:first');

        // Move the photo to the top, and
        // apply a random entrance animation

        elem.appendTo(photos)
            .addClass('animated')
            .addClass( entrances[Math.floor(entrances.length*Math.random())] );

        setTimeout(function(){

            // Remove the classess
            elem.attr('class','');

            // The animation is complate!
            // Allow clicks again:
            ignoreClicks = false;

        },1000);
    });

    // Start an automatic slideshow
    var slideshow = setInterval(function(){

        // Simulate a click every 1.5 seconds
        $('.arrow.next').trigger('click',[true]);

    }, 1500);

});

I haven't used all the effects that animate.css provides, but you can find a full list at its github page.

All that we are left to do, is to write a few CSS styles.

The CSS

I won't be showing all of the styles here, only those that are directly responsible for the photo stack:

assets/css/styles.css

#photos{
    margin:0 auto;
    padding-top:120px;
    width:450px;
    position:relative;
}

#photos li{
    position:absolute;
    width:450px;
    height:450px;
    overflow:hidden;
    background-color:#fff;
    box-shadow: 1px 1px 1px #ccc;
    z-index:10;

    -webkit-animation-duration: 1s;
    -moz-animation-duration: 1s;
    animation-duration: 1s;
}

#photos li a{
    position:absolute;
    top:6px;
    left:6px;
    right:6px;
    bottom:6px;
    background-size: cover;
    text-indent:-9999px;
    overflow:hidden;
}

To change the duration of the animations, you will have to supply the animation-duration property. In the fragment above, I have set it to 1 second. More properties that you can set are animation-delay for the delay before the animation is triggered, and animation-iteration-count for the number of repetitions.

Done!

With this our animated photo stack effect is complete! You can use this example as a lightweight slideshow that works smoothly even on mobile devices.

Bootstrap Studio

The revolutionary web design tool for creating responsive websites and apps.

Learn more

Related Articles

علیرضا معظمی

nice, but unwanted scroll that appears in small screen (like 800×600) can be easily avoided :)

This is great i will include this to my new project thanks for sharing

I like too.

Casco Romano

Very good and original Martin, I wait to be able to use it in a near(next) project.
Regards and thank you very much

like
i have problem with overflow

Excellent as always

wow, excellent tutorial this i am learn something new about html,css. Thanks...

Hi Martin, I always see special something in your tuts, thanks, I will use it for my projects.

Another great tutorial, thanks for sharing.

Gunjesh Kumar

Great Post and Tutorial. The photo stack effect is really nice. Thanks for sharing.

Hi Martin.
Its good. Amazing Stunning movements.Any way thanks for sharing.....

Thank you for this nice tutorial, you rock :) !

Awais Raza

Good effect, and easy to learn. Keep it up Martin.

I like this effect so much, thanks for sharing :)