Portfolio Zoom Slider with jQuery

In this tutorial we are going to create some nice effects for a portfolio or similar website with jQuery. We will create a tiny slider and integrate it with the […]

In this tutorial we are going to create some nice effects for a portfolio or similar website with jQuery. We will create a tiny slider and integrate it with the amazing Cloud Zoom plugin and the elegant Fancybox plugin.

The idea is to give the user the option to view details of a portfolio item by zooming it on hover, and to allow a full view by clicking. Moreover, we want to have a couple of images for each item, hence we will create a slider.

When integrating jQuery scripts, it sometimes happens that there are conflicts, be it because of some shared attribute or because of some specific structure that is needed by each jQuery plugin. In this tutorial we will bump into some of these conflicts and we will adapt some lines of code in order to bypass them.

So, let’s start with the markup!

The Markup

For each item we will have a div element. There we will add an element for the thumbnails slider which we will give the class “thumb_wrapper” and an element for the description with the respective class name:

<div class="item">
	<div class="thumb_wrapper">
		<div class="thumb">
			<ul>
				<li>
					<a href="images/formstack1.jpg">
						<img src="images/thumbs/formstack1.jpg" alt="Formstack 1"/>
					</a>
				</li>
				<li>...</li>
				...
			</ul>
		</div>
		<a class="prev" href="#"></a>
		<a class="next" href="#"></a>
		<span>Hover to zoom, click to view</span>
	</div>
	<div class="description">
		<h2>Portfolio Item</h2>
		<p>Some description</p>
	</div>
</div>

The link element which wraps the image will have the href pointing to the large image. Both plugins that we are using take advantage of that structure. They will build their elements with the information provided in the href attribute.

Additonally, we will add the following attributes and class name to each link element:

<a rev="group1" rel="zoomHeight:200, zoomWidth:400, adjustX: 10, adjustY:-4, position:'body'" class='cloud-zoom' href="images/formstack1.jpg">...</a>

The “rel” attribute is actually used by both plugins but we will change the Fancybox plugin, so that it used the “rev” attribute instead. The Fancybox plugin can create a gallery if we give the same “rev” value to a group of images. So, our thumbnails in the first item will all have the “group1” rev value and the the thumbnails in the second item will have “group2” and so forth.
For configuring the Cloud Zoom plugin, we will add some parameters to the “rel” attribute.
For more information on the configuration of the plugins, please visit the Cloud Zoom plugin and Fancybox plugin websites.
The position:’body’ value is an adapted value that we will come to later, when we go into the jQuery.

Let’s look at the styling.

The CSS

First we will define the style for the item:

.item{
	float:left;
	width:100%;
	clear:both;
	margin:35px 0px;
}

Now, we will position the thumb wrapper which contains the navigation and the thumbnail slider:

.thumb_wrapper{
	width:290px;
	height:107px;
	position:relative;
	float:left;
	margin:20px 40px 0px 0px;
}

The navigation elements will be positioned absolutely. That’s why we needed to set the parent to a relative position. The common style for both navigation elements is:

.thumb_wrapper a.prev,
.thumb_wrapper a.next{
	width:30px;
	height:30px;
	position:absolute;
	top:50%;
	margin-top:-15px;
	outline:none;
	cursor:pointer;
}

And the individual style for each navigation element is the following:

.thumb_wrapper a.prev{
	left:0px;
	background:transparent url(../images/fancy_nav_left.png) no-repeat top left;
}
.thumb_wrapper a.next{
	right:0px;
	background:transparent url(../images/fancy_nav_right.png) no-repeat top left;
}

The style for the small info span under the slider:

.thumb_wrapper span{
	display:block;
	text-align:center;
	font-size:11px;
	font-style:italic;
	margin-top:3px;
}

The thumb element is the container for the unordered list of thumbnails. We will set the overflow to hidden, since we don’t want our list to show:

.thumb{
	margin-left:40px;
	width:210px;
	height:107px;
	overflow:hidden;
	-moz-box-shadow:1px 1px 3px #555;
	-webkit-box-shadow:1px 1px 3px #555;
	box-shadow:1px 1px 3px #555;
}

The ul for the thumbnails will have a dynamically calculated width which will overwrite the following one:

.thumb ul{
	list-style:none;
	width:800px;
	height:107px;
}

The list items have to flow left so that we have all the thumbnails in a line. The idea is, to animate the ul to the right position, revealing the next/previous thumbnail in our “line”.

.thumb ul li{
	float:left;
}

Let’s decorate the thumbnail images:

.thumb ul li a img{
	border:5px solid #fff;
}

The description will be floating right of the slider:

.description{
	width:620px;
	float:right;
}

And that was all the style! That’s take a look at the JavaScript.

The JavaScript

The main idea is to create a little slider where the user can navigate through the thumbnails of a portfolio item. Then, when hovering over the thumbnail, we want a zoomed version of the hovered part of the thumbnail to appear on the right side. When clicking on a thumbnail, we want the Fancybox to appear, allowing the user to view the full image and navigate through the set.

So, we will start by including the necessary stylesheets and scripts. First, we will add the stylesheets to the head of our HTML:

<link rel="stylesheet" type="text/css" href="cloud-zoom/cloud-zoom.css" />
<link rel="stylesheet" type="text/css" href="fancybox/jquery.fancybox-1.3.4.css" />

Then, we will add all the scripts in the end of the HTML:

<script type="text/javascript" src="http://code.jquery.com/jquery-1.4.4.min.js"></script>
<script type="text/javascript" src="fancybox/jquery.easing-1.3.pack.js"></script>
<script type="text/javascript" src="fancybox/jquery.fancybox-1.3.4.js"></script>
<script type="text/javascript" src="cloud-zoom/cloud-zoom.1.0.2.js"></script>

In our jQuery function we will first initialize the Fancybox and then we will define the functionality of the slider. As mentioned before, the Cloud Zoom plugin parameters are set in the “rel” attribute of the link element that wraps the thumbnail image.

Let’s initialize the Fancybox:

$("#content .cloud-zoom").fancybox({
	'transitionIn'	:	'elastic',
	'transitionOut'	:	'none',
	'speedIn'		:	600,
	'speedOut'		:	200,
	'overlayShow'	:	true,
	'overlayColor'	:	'#000',
	'cyclic'		:	true,
	'easingIn'		:	'easeInOutExpo'
});

We need to deal with a conflict now, which is caused by the Cloud Zoom Plugin adding a div element on top of our link element. It conflicts with the Fancybox Plugin since we cannot click the link element anymore (it’s covered). So, we will add a little function that will trigger the click on the link element whenever we click on the div with the class “mousetrap” that gets generated by the Cloud Zoom Plugin:

$("#content .mousetrap").live('click',function(){
	$(this).prev().trigger('click');
});

Now, we will define some variables for our slider:

var $content	= $('#content'),
$thumb_list = $content.find('.thumb > ul');

The slider ul needs to get a width assigned to it which will be the sum of the widths of each thumbnail inside. We will also define the click events on the navigation buttons:

$thumb_list.each(function(){
	var $this_list	= $(this),
	total_w		= 0,
	loaded		= 0,
	//preload all the images first
	$images		= $this_list.find('img'),
	total_images= $images.length;
	$images.each(function(){
		var $img	= $(this);
		$('').load(function(){
			++loaded;
			if (loaded == total_images){
				$this_list.data('current',0).children().each(function(){
					total_w	+= $(this).width();
				});
				$this_list.css('width', total_w + 'px');

				//next / prev events

				$this_list.parent()
				.siblings('.next')
				.bind('click',function(e){
					var current = $this_list.data('current');
					if(current == $this_list.children().length -1) return false;
					var	next	= ++current,
					ml		= -next * $this_list.children(':first').width();

					$this_list.data('current',next)
					.stop()
					.animate({
						'marginLeft'	: ml + 'px'
					},400);
					e.preventDefault();
				})
				.end()
				.siblings('.prev')
				.bind('click',function(e){
					var current = $this_list.data('current');
					if(current == 0) return false;
					var	prev	= --current,
					ml		= -prev * $this_list.children(':first').width();

					$this_list.data('current',prev)
					.stop()
					.animate({
						'marginLeft'	: ml + 'px'
					},400);
					e.preventDefault();
				});
			}
		}).attr('src',$img.attr('src'));
	});
});

And that’s all! We adapted the Fancybox script slightly in order to show the navigation arrows constantly when hovering over the full image. Also, we adapted the z-indexes of the Fancybox elements in the stylesheet (we added 10000 to each z-index) in order to work with the other elements in the page and the Cloud Zoom elements. In the Cloud Zoom script we added another case for the position, since we need to append the zoom element to the body using the absolute positions of the thumbnails.

We hope you enjoyed the tutorial and find it useful!

Tagged with:

Manoela Ilic

Manoela is the main tinkerer at Codrops. With a background in coding and passion for all things design, she creates web experiments and keeps frontend professionals informed about the latest trends.

Stay up to date with the latest web design and development news and relevant updates from Codrops.