Go to homepage

Projects /

3D Items Quick View

A simple 3D animation for your gallery items, to make it easy for users to discover more about your products without having to leave the page.

3D Items Quick View
Check our new component library →

The idea behind this resource is: if I have a gallery of products, I'm gonna pick the best image for each one of them. But what if one image is not enough? The client clicks on the product, he/she goes to the single product page, and, in most cases, they'll find a slideshow there. However, if they could see more images of the same product before moving to the product page, there'd be more probabilities to drive them to what they really wanna buy. So we created a CSS3 and jQuery powered slider for each item of the gallery, hidden by default and triggered by the :hover selector on no-touch devices and a tap on touch devices.

About IE9: even though the 3D effect and the slider won't be visible, the gallery will work just fine.

Of course there can be other uses for this code snippet. Feel free to experiment!

Creating the structure

The main structure is an unordered list. Each list items contains a nested unordered list.  In addition to the nested unordered list (the 3+ product images) we needed some other elements: the product info (title and price), the navigation (2 arrows to navigate between preview images) and the 3D effect trigger (visible on mobile only, where we can't use the hover effect as trigger).

      <ul class="cd-item-wrapper">
         <li class="cd-item-front"><a href="#0"><img src="img/thumb-1.jpg"></a></li>
         <li class="cd-item-middle"><a href="#0"><img src="img/thumb-2.jpg"></a></li>
         <li class="cd-item-back"><a href="#0"><img src="img/thumb-3.jpg"></a></li>
         <li class="cd-item-out"><a href="#0"><img src="img/thumb-4.jpg"></a></li>
         <!-- <li class="cd-item-out">...</li> -->
      </ul> <!-- cd-item-wrapper -->

      <div class="cd-item-info">
         <b><a href="#0">Product Name</a></b>
      </div> <!-- cd-item-info -->

         <ul class="cd-item-navigation">
            <li><a class="cd-img-replace" href="#0">Prev</a></li>
            <li><a class="cd-img-replace" href="#0">Next</a></li>

      <a class="cd-3d-trigger cd-img-replace" href="#0">Open</a>

      <!-- ... -->

Adding style

To create the 3D effect we used CSS3 3D transformations. For the 3D effects to work we need to set a perspective value to the parent element (the nested unordered list). We declared 4 classes for the list items: .cd-item-front, .cd-item-middle and .cd-item-back for the first 3 list items, while the class .cd-item-out is used for all the other (not visible) list items - in case you want to add more images.

.cd-item-wrapper {
  perspective: 500px;
  perspective-origin: 50% -30%;

.cd-item-wrapper li {
  position: absolute;
  top: 0;
  left: 0;
  transition: all 0.4s;

.cd-item-wrapper li.cd-item-front {
  position: relative;
  z-index: 3;

.cd-item-wrapper li.cd-item-middle {
  z-index: 2;

.cd-item-wrapper li.cd-item-back {
  z-index: 1;

.cd-item-wrapper li.cd-item-out {
  /* picture not visible - use this class in case you have more than 3 pictures per item */
  z-index: 0;
  opacity: 0;

Note that the second value passed to the perspective-origin property (Y axis) is negative. This way, when we push the list items along the Z axis, they are visible on top of the frontal list item.

3d effect animation

On no-touch devices, to trigger the 3D effect all we need is the hover selector:

.no-touch #cd-gallery-items > li:hover .cd-item-middle {
  transform: translate3d(0, 0, -20px);
  opacity: .8;
.no-touch #cd-gallery-items > li:hover .cd-item-back {
  transform: translate3d(0, 0, -40px);
  opacity: .4;

On touch devices, instead, we use the class .active triggered by a tap on the .cd-3d-trigger anchor tag.

Finally we need 2 more classes to handle the slide-out effect of the frontal list item. We use li.move-right to push out the item, and li.hidden to hide it at the end of the transition (with some jQuery help):

.cd-item-wrapper li.move-right {
  transform: translate3d(200px, 0, 0);
  opacity: 0;
  z-index: 4 !important;

.cd-item-wrapper li.hidden {
  /* used to hide the picture once it's pushed out - to the right */
  display: none !important;

Events handling

We defined two functions to control the navigation appearance: updateNavigation() and hideNavigation():

function updateNavigation(navigation, container) {
   //container is the .cd-item-wrapper element
   var isNextActive = ( container.find('.cd-item-middle').length > 0 ) ? true : false,
       isPrevActive =   ( container.children('li').eq(0).hasClass('cd-item-front') ) ? false : true;
   (isNextActive) ? navigation.find('a').eq(1).addClass('visible') : navigation.find('a').eq(1).removeClass('visible');
   (isPrevActive) ? navigation.find('a').eq(0).addClass('visible') : navigation.find('a').eq(0).removeClass('visible');

function hideNavigation(navigation) {

On no-touch devices, we use the hover event to toggle the slider navigation visibility; on touch devices, instead we use the click event on the .cd-3d-trigger anchor tag.

When user taps on the slider navigation, we change the classes assigned to the .cd-item-wrapper li elements to create the 3D slide effect.

var galleryNavigation = $('.cd-item-navigation a');
//change image in the slider
galleryNavigation.on('click', function(){
   var navigationAnchor = $(this),
       direction = navigationAnchor.text(),
       activeContainer = navigationAnchor.parents('nav').eq(0).siblings('.cd-item-wrapper');
   ( direction=="Next") ? showNextSlide(activeContainer) : showPreviousSlide(activeContainer);
   updateNavigation(navigationAnchor.parents('.cd-item-navigation').eq(0), activeContainer);

Project duplicated

Project created

Globals imported

There was an error while trying to export your project. Please try again or contact us.