Creating a 3D Interactive Gallery with CSS and jQuery

Today I will guide you through a series of steps to achieve a beautiful 3D interactive gallery using only CSS3 and jQuery. This tutorial is inspired by the website of Tapmates. With this tutorial we will add some interesting interactions which can be applied to anything from an image driven website to your portfolio website. Let’s begin (Webkit Browser Only).

Creating a 3D Interactive Gallery with CSS and jQuery


Creating a 3D Interactive Gallery with CSS and jQuery

Step 1: Laying Out the Images

The HTML

<div class="gallery">
  <div class="item">
    <img align="left" src="img/c2NAjXD.jpg"/>
  </div>
  <div class="item">
    <img align="left" src="img/FeCziip.png"/>
  </div>
  <div class="item">
    <img align="left" src="img/OYlw7Pw.jpg?"/>
  </div>
  <div class="item">
    <img align="left" src="img/MVammek.jpg?"/>
  </div>
  <div href="#" class="item">
    <img align="left" src="img/gfp57KR.png"/>
  </div>
  <div class="item">
    <img align="left" src="img/FeCziip.png"/>
  </div>
</div>

The CSS

body {
    margin: 0;
}

.gallery {
    margin: 0 auto;
    width: 700px;
}
.gallery .item{
    cursor: pointer;
    position: relative;
    display: block;
    float: left;
    z-index: 1;
}

.gallery .item img {
    -webkit-transition-property: all;
    -webkit-transition-duration: 0.7s;
    box-shadow:  -10px 10px 25px rgba(0,0,0,0.25);
    max-width: 100%;
    width: 190px;
    height: 340px;
}

Firstly, we will simply line up a bunch of images we want in our gallery to be interactive with the markups above. Noted that all those images are placeholders so feel free to change anything. If you are changing images, I recommend you find images that are equivalent in size so that every image will be aligned correctly. If not, then you may need other plugins such as Woomark or Masonry to help align different sized images into a grid.

Step 2: Transforming

The HTML

<div class="gallery">
  <div class="item">
    <img align="left" src="img/c2NAjXD.jpg"/>
  </div>
  <div class="item">
    <img align="left" src="img/FeCziip.png"/>
  </div>
  <div class="item">
    <img align="left" src="img/OYlw7Pw.jpg"/>
  </div>
  <div class="item">
    <img align="left" src="img/MVammek.jpg"/>
  </div>
  <div href="#" class="item">
    <img align="left" src="img/gfp57KR.png"/>
  </div>
  <div class="item">
    <img align="left" src="img/FeCziip.png"/>
  </div>
</div>

The CSS

body {
    background: url(img/LBONKMh.jpg) repeat fixed right bottom;
    margin: 0;
}

.gallery {
    margin: 0 auto;
    width: 700px;
}
.gallery .item{
    cursor: pointer;
    position: relative;
    display: block;
    float: left;
    margin: 0 50px -175px;
    z-index: 1;
    transform-origin:20% 40%;
    -webkit-transform: translate3d(0, -50px, 0) scaleY(0.57) rotate(-45deg);
    -webkit-transition-property: all;
    -webkit-transition-duration: 0.7s;
}

.gallery .item img {
    -webkit-transition-property: all;
    -webkit-transition-duration: 0.7s;
    box-shadow:  -10px 10px 25px rgba(0,0,0,0.25);
    max-width: 100%;
    width: 190px;
    height: 340px;
}

In this step, we tilted each image with the very useful object manipulation style called transform which allows us to freely transform any HTML object. Although it is useful, tilting an object like this causes the images to stack up and we don’t want that. In order to solve this, I added a workaround margin style to keep them separated enough for us to interact with. We’ve also added a transition style to be used in our interactive part in the next step.

Step 3: Interaction

The HTML

<div class="gallery">
  <div class="item">
    <img align="left" src="img/c2NAjXD.jpg"/>
  </div>
  <div class="item">
    <img align="left" src="img/FeCziip.png"/>
  </div>
  <div class="item">
    <img align="left" src="img/OYlw7Pw.jpg?1"/>
  </div>
  <div class="item">
    <img align="left" src="img/MVammek.jpg?1"/>
  </div>
  <div href="#" class="item">
    <img align="left" src="img/gfp57KR.png"/>
  </div>
  <div class="item">
    <img align="left" src="img/FeCziip.png"/>
  </div>
</div>

The CSS

body {
    background: url(img/LBONKMh.jpg) repeat fixed right bottom;
    margin: 0;
}

.gallery {
    margin: 0 auto;
    width: 700px;
}

.gallery .item{
    cursor: pointer;
    position: relative;
    display: block;
    float: left;
    margin: 0 50px -175px;
    z-index: 1;
    transform-origin:20% 40%;
    -webkit-transform: translate3d(0, -50px, 0) scaleY(0.57) rotate(-45deg);
    -webkit-transition-property: all;
    -webkit-transition-duration: 0.7s;
}

.gallery .item img {
    -webkit-transition-property: all;
    -webkit-transition-duration: 0.7s;
    box-shadow:  -10px 10px 25px rgba(0,0,0,0.25);
    max-width: 100%;
    width: 190px;
    height: 340px;
}

.gallery .item:hover {
    z-index: 2;
    -webkit-transform: translate3d(0, -50px, 0) scaleY(0.57) rotate(-45deg) scale(1.2);
}

.gallery .item.clicked{
    z-index: 3;
    -webkit-transform:none;
}

The JS

$(document).ready(function() {
    $(".item").click(function (e) {
      e.stopPropagation();
      $(".item").removeClass("clicked");
      $(this).toggleClass("clicked");
      $("body").addClass("showing-item");
    });
    $('html').click(function() {
       $(".item").removeClass("clicked");
       $("body").removeClass("showing-item");
    });
});

Make sure you have jQuery included in your HTML file. Any version newer than 1.9.1 is preferable. At this stage, we will make it a little interactive by adding a hover effect and make it clickable. For the hover effect, we simply add a hover style for each image scaling it up a little to let the user know it is clickable. For the click function, we will need jQuery to help us define a class for the clicked state. As you can see in the JS part, the new “clicked” class will be added every time you click the images. The “clicked” class will remove all the transformation we did in the previous step temporarily for the users to see each image as it was intended. The second part is to clear the clicked state whenever the user selects anywhere outside the image.

Step 4: Adding Captions

The HTML

<div class="gallery">
  <div class="item">
    <img align="left" src="img/c2NAjXD.jpg"/>
    <span class="caption">
      <h1>
        BucketListly.com
      </h1>
      <p>
        Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris
      </p>
    </span>
  </div>
  <div class="item">
    <img align="left" src="img/FeCziip.png"/>
    <span class="caption">
      <h1>
        BucketListly.com
      </h1>
      <p>
        Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris
      </p>
    </span>
  </div>
  <div class="item">
    <img align="left" src="img/OYlw7Pw.jpg?1"/>
    <span class="caption">
      <h1>
        BucketListly.com
      </h1>
      <p>
        Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris
      </p>
    </span>
  </div>
  <div class="item">
    <img align="left" src="img/MVammek.jpg?1"/>
    <span class="caption">
      <h1>
        BucketListly.com
      </h1>
      <p>
        Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris
      </p>
    </span>
  </div>
  <div href="#" class="item">
    <img align="left" src="img/gfp57KR.png"/>
    <span class="caption">
      <h1>
        BucketListly.com
      </h1>
      <p>
        Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris
      </p>
    </span>
  </div>
  <div class="item">
    <img align="left" src="img/FeCziip.png"/>
    <div class="caption">
      <h1>
        BucketListly.com
      </h1>
      <p>
        Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris
      </p>
    </div>
  </div>
</div>

The CSS

body {
    background: url(img/LBONKMh.jpg) repeat fixed right bottom;
    margin: 0;
}
body.showing-item .item:not(.clicked){
     -webkit-filter: blur(2px) grayscale(0.5) opacity(0.8);
}
.gallery {
    margin: 0 auto;
    width: 700px;
}
.gallery .item{
    cursor: pointer;
    position: relative;
    display: block;
    float: left;
    margin: 0 50px -175px;
    z-index: 1;
    transform-origin:20% 40%;
    -webkit-transform: translate3d(0, -50px, 0) scaleY(0.57) rotate(-45deg);
    -webkit-transition-property: all;
    -webkit-transition-duration: 0.7s;
}
.gallery .item:hover {
    z-index: 2;
    -webkit-transform: translate3d(0, -50px, 0) scaleY(0.57) rotate(-45deg) scale(1.2);
}
.gallery .item.clicked{
    z-index: 3;
    -webkit-transform:none;
}
.gallery .item .caption{
    display: none;
    border-radius: 3px 3px;
    font-family: helvetica, arial;
    background: white;
    padding: 10px;
    box-shadow: 0 1px 2px rgba(0,0,0,0.45);
    width: 300px;
}
.gallery .item .caption:after{
background-color: #fff;
    box-shadow: -2px 2px 2px 0 rgba( 178, 178, 178, .4 );
    content: "&#092;&#048;0a0";
    display: block;
    height: 15px;
    left: -5px;
    position: absolute;
    top: 50%;
    margin-top: -7px;
    -webkit-transform: rotate( 45deg );
    width:  15px;
}
.gallery .item.left .caption:after{
    right: -8px;
    left: auto;
    box-shadow: 2px -1px 2px 0 rgba( 178, 178, 178, .4 );
}
.gallery .item .caption h1{
    color: black;
    font-weight: 100;
    text-align: center;
    letter-spacing: -1px;
    margin: 0 0 5px;
    margin-bottom: 10px;
border-bottom: 1px solid #EFEFEF;
padding-bottom: 10px;
}
.gallery .item .caption p{
     color: #444;  
    font-weight: 100;}
.gallery .item.clicked .caption{
    position: absolute;
    top: 25px;
    display: inline; 
    -webkit-transition-property: display;
    -webkit-transition-duration: 0.7s;
}
.gallery .item.clicked.right .caption {
    left: 115%;
    margin-left: 15px;

}
.gallery .item.clicked.left .caption {
    right: 115%;
     margin-right: 15px;
}
.gallery .item.clicked img {
    box-shadow:  0 0 25px rgba(0,0,0,0.25);
    -webkit-transform: scale(1.25);
}
.gallery .item img {
    -webkit-transition-property: all;
    -webkit-transition-duration: 0.7s;
    box-shadow:  -10px 10px 25px rgba(0,0,0,0.25);
    max-width: 100%;
    width: 190px;
    height: 340px;
}

The JS

$(document).ready(function () {
    $(".item").click(function (e) {
        e.stopPropagation();
        $(".item").removeClass("clicked");
        $(this).toggleClass("clicked");
        $("body").addClass("showing-item");

        var offset = $(this).offset();
        var pos = offset.left + $(this).width()
        var center = $(".gallery").width() / 2;
        if (pos > center) {
            var align = "left";
        } else {
            var align = "right";
        }
        $(this).removeClass(".left, .right").addClass(align);

        return false;
    });

    $('html').click(function () {
        $(".item").removeClass("clicked");
        $("body").removeClass("showing-item");
    });
});

This is the last step and it is probably the most complex step out of all. In this step I’ve decided to add a caption to each image and in order to do that I’ve added extra HTML markup and CSS, to style the caption box to look like a speech bubble. The styles here are quite straightforward except the new style I used to focus the clicked image and blur all the others. The style is called filter and it allows us to manipulate photos, from adding a blur effect to sepia. In this step, I simply blurred any objects that aren’t in a clicked state.

For the JS part, in order to make the caption work, I have to find a way to detect whether the caption will be shown on the left or on the right. I’ve decided to write a little function to check the position of the image and if the x axis exceeds the center of the page then the caption will show on the left, if not the caption will show on the right as usual. With everything in place, viewers will see beautifully transitioned captions appear every time they click on the images.

Conclusion

Now you get a beautiful 3D interactive gallery for your website. Feel free to customize the code as you see fit and show us in the comments below.

If you need help or have a suggestion, feel free to let me know anytime.

Opinions expressed in this article are those of the author and not necessarily those of Onextrapixel.