How to create a mosaic transition effect between two photos using jQuery

While playing around with some jQuery effects, I ended up building a mosaic transition effect between two photos, and I decided to wrap it up in a tutorial and share it with you (source code). First, have a look at the demo to check what we will end up building. There is another version of the effect as well.

To begin with, we will use two photos with the same dimensions. The only HTML code we’ll need (apart from loading the scripts) is an html element (it can be whatever you want; I’m using a div) that we will use as our container. It should have a unique id; I named it “mosaic”.

The only piece of CSS code we’ll have to write is the following (replace the images’ filenames with yours):

Now, let’s talk JavaScript.

First of all, we’ll include almost all of the code inside a $(document).ready function. We begin by declaring and initialising some variables: width and height contain our photos’ dimensions, elements is an array which will hold the elements we’ll create that will form the overlay of the base photo, count will be used later to help us iterate through the elements array, and el holds the HTML element we are using as a container. We also set the width and height of the element to the dimensions we just specified.

The next step is to specify the number of the horizontal and vertical pieces we want our mosaic to consist from. Then, based on this selection, we calculate the total number of pieces, as well as their dimensions.

Afterwards, based on the above values, we create a set of span elements (assigning unique IDs to them), which will act as the tiles that will form the mosaic, and will be used to perform the transition effect.

Since we want the tiles of the mosaic to form a complete photo, we will use the photo as a sprite. We already specified it as the background of all the span elements using the #mosaic span.hover CSS rule, so we just need to make a few calculations to calculate which part of the photo will need to be visible in each element, and modify their background-position to accomplish that. We append all of the newly created elements to the container, and also add them to the elements array, so they can be retrieved later.

Finally, we apply the dimensions we calculated before in all of the span elements, and we call the toggleDisplay function (I’ll explain it in a bit) every 100 milliseconds.

This wraps-up what is included in the $(document).ready function; we’ll continue with the toggleDisplay function I mentioned before.

It’s a very simple function, which grabs the next item set to be checked from the elements array (based on the count variable), and toggles its opacity value. Finally, it iterates the count variable.

Apart from the above, by performing some minor alterations to the code, we can change the sequence of the transition to accomplish other effects. For example, by shuffling the elements array randomly, we can achieve this effect.

Updated on 1st of May, 2013: Based on the comments by R, I added a third demo.

source code | demo (version 1) | demo (version 2) | demo (version 3)

Photo by ~sufined

  • R

    How would I create a delay in the version_2.js so that the next picture doesn’t instantly start fading in? I would love to have an effect where it’d fade in, pause (so viewer can see the whole image), and then fade another picture.

    Thank you!!

    • R

      Also, how would I add in more pictures? Right now I seem to be limited to only the two pictures: #mosaic and #mosaic span.hover

      Thank you

      • Stathis

        Check this demo. It contains a delay between the transitions, and also works with multiple images. source code

        For any questions/suggestions, please let me know. :)

  • http://blog.dreamcss.com ravindra

    Is it possible to use more then 2 images for Create mosaic transition effect. my idea to use minimum 3 to 5 images to create mosaic transition effect.

    • Stathis

      Sorry for the delay, I missed your comment. It’s sure possible, but I don’t know if it’s going to be suitable to modify my example or you’re going to need another approach.

      One quick idea (based on the tutorial) is to change the background-image value of an image as soon as it’s not visible any more, but you’ll probably have to pre-load the images somehow.

  • Joe

    Would you have a different source code for version three?
    The js is extremely difficult to read compared to your other versions.

    • Stathis

      Hello Joe,

      What do you mean by “extremely difficult to read”?

  • Brett

    Very nice work, thank you! I was wondering if there is any way to get the fade transition along with the mosaic effect you already have… is this possible at all? Thank you again for the great work, very impressive!

    Cheers

    • Stathis

      Hello Brett,

      The individual tiles which together form the mosaic effect, already have a fade transition.

      Can you explain in more detail what do you mean?

  • Brett

    Hey Stathis, just sent you an email with more detail. Thank you for your help!

  • Sokngim

    Hello, I want you to tell about how to add more photos. Thanks

    • http://burnmind.com/ StathisG

      Hello Sokngim,

      Please have a look at this comment (a reply to ravindra), where I mention an idea about the same request.

  • Erika

    Hi, Thank you so much for taking the time to put together this tutorial and making the actual outcome so beautiful. I was wondering how I would go about making it so that the images didn’t turn until I actually clicked on them. I apologize if this question is rudimentary to most, but i”m a newb with jquery and just learning about it and javascript. Thank you so much.

    • http://burnmind.com/ StathisG

      Hi Erika,

      Sorry for the delayed reply, I’ve been on a long vacation and I’m just catching up with everything. You can do something similar to the following:

      Assuming that you have a a button that you’ll have to click to change the image

      
      click me!
      

      in your JavaScript file (I’m using the first version as a base), replace the following line

      
      setInterval(toggleDisplay, 100);
      

      with this block of code

      
      button = $('#click-me');
      button.click(function(){
          count = 0;
          timer = setInterval(toggleDisplay, 100);
          $(this).prop("disabled", true);
      });
      

      and this line

      
      count = (count + 1) % total_pieces;
      

      with this block of code

      
      if(count == total_pieces - 1) {
          clearInterval(timer);
          button.removeAttr('disabled');
      }
      count++;
      
      • Erika

        thanks, sorry for it being so long for me to get back to you. i appreciate it !

        • http://burnmind.com/ StathisG

          You’re welcome, I’m glad I could help. :)