A "product quick view" modal window, animated using CSS3 and Velocity.js, that provides the user a quick access to the main product information.

There are some patterns in the e-commerce design world aimed at increasing the conversion rate by simplifying the user experience. Other patterns try to achieve the same goal by providing additional information where needed. The product quick view modal belongs to the second category.

The standard process is straightforward: click on the quick view button to fire a modal with additional information and a call-to-action button. By building our resource, we didn't reinvent the wheel: at the end you still get the same result. We tried to enhance the transition from point A to point B though.

These days native applications are using the full power of the device and motion design notions to provide the best UX possible. The web needs to run at the same speed. There are great tools like Bounce.js by Joel Besada and Velocity.js by Julian Shapiro that can help you build smooth animations.

Getting back to our nugget, here is a quick animation to show you what we had in mind (.gif created in After Effects):

Creating the structure

The gallery is an unordered list. The cool stuff happens into the .cd-quick-view <div> , which contains a slider ( .cd-slider-wrapper ) and the product information ( .cd-item-info ).

<ul class="cd-items cd-container"> <li class="cd-item"> <img src="img/item-1.jpg" alt="Item Preview"> <a href="#0" class="cd-trigger">Quick View</a> </li> <!-- cd-item --> <li><!-- ... --></li> </ul> <!-- cd-items --> <div class="cd-quick-view"> <div class="cd-slider-wrapper"> <ul class="cd-slider"> <li class="selected"><img src="img/item-1.jpg" alt="Product 1"></li> <li><img src="img/item-2.jpg" alt="Product 2"></li> <li><img src="img/item-3.jpg" alt="Product 3"></li> </ul> <!-- cd-slider --> <ul class="cd-slider-navigation"> <li><a class="cd-next" href="#0">Prev</a></li> <li><a class="cd-prev" href="#0">Next</a></li> </ul> <!-- cd-slider-navigation --> </div> <!-- cd-slider-wrapper --> <div class="cd-item-info"> <h2>Produt Title</h2> <p>Lorem ipsum dolor sit amet, consectetur adipisicing...</p> <ul class="cd-item-action"> <li><button class="add-to-cart">Add to cart</button></li> <li><a href="#0">Learn more</a></li> </ul> <!-- cd-item-action --> </div> <!-- cd-item-info --> <a href="#0" class="cd-close">Close</a> </div> <!-- cd-quick-view -->

Adding style

First of all, the quick view effect is hidden on small devices. The reason being that on a phone it's easier to access directly the product page.

That said, most of the animations have been created in jQuery using Velocity.js to avoid jank effects. The dark overlay layer was created by animating the body::after pseudo-element:

body::after { /* dark overlay layer - visible when we fire .cd-quick-view */ position: fixed; top: 0; left: 0; width: 100%; height: 100%; background: rgba(71, 55, 78, 0.8); visibility: hidden; opacity: 0; transition: opacity .3s 0s, visibility 0s .3s; } @media only screen and (min-width: 1024px) { body.overlay-layer::after { visibility: visible; opacity: 1; transition: opacity .3s 0s, visibility 0s 0s; } }

A lot of elements are animated or have a CSS3 transition. To keep a good performance we used the translateZ(0) hack on some of them (while we wait for the new will-change property to get more browser support).

.cd-quick-view { display: block; position: fixed; max-width: 900px; visibility: hidden; /* Force Hardware Acceleration in WebKit */ transform: translateZ(0); -webkit-backface-visibility: hidden; backface-visibility: hidden; will-change: left, top, width; z-index: 1; }

No more CSS tricks worth mentioning. Let's dive into jQuery!

Events handling

When user clicks the .cd-trigger element, we evaluate the top, left and width values of the gallery selected image and assign them to the .cd-quick-view element (which is in position: fixed ). This way the .cd-quick-view has the same dimensions of the gallery image and completely covers it (meanwhile the gallery image is hidden using the .empty-box class).

We then animate the .cd-quick-view element. First step we animate the .cd-quick-view width to the sliderFinalWidth (this is a variable set to 400 in the .js file). This value represents the width of the slider image inside the quick view panel; we also animate the .cd-quick-view position (top and left values) so that it's centered in the viewport (the height of the quick view panel is automatically given by the image slider height). Note that during this step, only the image slider is visible, while the rest of the quick view content is hidden.

Second step we change the .cd-quick-view width to its final value ( 80% of the viewport width, with a max value of 900 - defined by the maxQuickWidth variable) and change its position accordingly so that the panel is always centered. After this second step, we assign the .add-content class to the .cd-quick-view to show its hidden content.

For the animation, we used Velocity.js, a plugin that re-implements jQuery's $.animate() for significantly greater performance (if you've never used it, you should definitively give it a try!). We used the 'spring' easing for the first animation step, and the \ease' for the second one.

$('.cd-trigger').on('click', function(event){ $('.cd-quick-view').css({ "top": topSelected, // this is the selected image top value "left": leftSelected, // this is the selected image left value "width": widthSelected, // this is the selected image width }).velocity({ //animate the quick view: animate its width and center it in the viewport //during this animation, only the slider image is visible 'width': sliderFinalWidth+'px', 'left': finalLeft+'px', // ($(window).width - sliderFinalWidth)/2, 'top': finalTop+ 'px', // ($(window).height - slider final height)/2, }, 1000, [ 400, 20 ]) .velocity({ 'width': quickViewWidth+'px', // 80% of the viewport 'left': quickViewLeft+'px', // 10% of the viewport }, 300, 'ease' ,function(){ //show quick view content $('.cd-quick-view').addClass('add-content'); }).addClass('is-visible'); //assign .overlay-layer class to the body, assign the .empty-box class to the selected .cd-item //... });