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):
👋 A new version of this component is available. Download now →.
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
//...
});
When user closes the quick view panel, the reverse animation is performed (in this case, 'ease' is used for both animations).
One additional note: before closing the quick view panel, we update the galley image src
value, this way it's equal to the slider visible image.