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 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 […]
PortfolioZoomSlider

From our monthly sponsor: Create your beautiful portfolio website with Squarespace. Start your free trial.Advertisement

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:

ML is a freelance web designer and developer with a passion for interaction design. She studied Cognitive Science and Computational Logic and has a weakness for the smell of freshly ground peppercorns.

http://www.codrops.com

Receive our bi-weekly Collective or official newsletter right in your inbox.

CSS Reference

Learn about all important CSS properties from the basics with our extensive and easy-to-read CSS Reference.

It doesn't matter if you are a beginner or intermediate, start learning CSS now.

Feedback 41

Comments are closed.
  1. Hello. Great script. Has anyone adapted the navigation to work with the slider ui? Could this be done?

  2. Thanks for the tutorial … I have managed to get it to work but when I want to put it in to the website I am working on the nav buttons and the click to view bigger image functions get knocked out so I am just left with the hover buttons. just new to this so am struggling to see what is conflicting with it. thanks

  3. i’d like to have an timeout before the zoomdiv starts is this possible whit an delay? and in what way would that woks?

  4. hello,
    is it possible to have only the thumbs and click to open pictures in big? (and so to delete the zoom rollover)?
    i’ve try to change code without succes
    thanks a lot
    (sorry for my english)

  5. Great… I love it ๐Ÿ™‚
    I have list of thumbs, and they have right margin 10px.

    So i just edited for prev & next:
    ml = -next * $this_list.children(‘:first’).width();

    to outerWidth(true):
    ml = -next * $this_list.children(‘:first’).outerWidth(true);

    And now it works ๐Ÿ™‚

    PS Edit intro text and add that scripts are edited, so if someone download original plugins, they will not work

  6. Just stumbled across this. Really neat combination of the two plugins. Well done.

  7. Great Job!

    I have one doubt, where can I change the Font in the title, like “Formstack”, “Know” or “Rocket Invoice”. I’ve lost trying to figure this out.

    Keep up the good work! ๐Ÿ™‚

  8. Very nice and useful job!
    Iยดm interested in the zoom and slider part.. I will try to display the boxes inline.

    Thanks for the tut..

  9. Cool tutorial, very useful. I noticed that when displaying the thumbnails side by side (floating one left and one right) Cloud Zoom’s mousetrap window does not work as expected. The thumbnail image only and not its containing div(s) show through the cloud-zoom overlay, despite the overlay’s high z-index. I notice that on the Cloud Zoom website, this bug is not apparent anywhere where thumbnails are obscured by the overlay, but I can’t pinpoint the problem. Does anyone have any insight on this? Thanks in advance!

  10. I fixed my own problem after digging around in Firebug some more. I can’t believe I missed it. In case someone else is having the same issue, here is the solution: In Cloud Zoom’s JavaScript source, find the line that creates and targets the “wrap” element. It’s around line 353. Get rid of the z-index:9999 style property in the wrap div that’s being generated. Don’t forget to make a comment with the original value and why you changed it! Now your Cloud Zoom overlay should sit on top of adjacent thumbnails.
    Also, if anyone is still having problems displaying the thumbnails inline, float one left and one right and change the width of the .item class to 50% so they can sit side by side (or whatever percentage of the container you want to use). Hope that helps someone else!

  11. Hi all,
    this is a great jquery tool..like all the others featured on this website!

    To fix the IE7 bug just add this conditional comment to your document head:

    .thumb_wrapper { width:290px !important; overflow:hidden; }

    It works also on IE8. The width is the one you have given to your thumbs container.

  12. Francesco, that still doesn’t work, as part of the next thumbnail is still showing and covering up the next (right) arrow.

    Anyone have a good solution for getting this working in IE7?

  13. OK, the solution was simple, add

    position:relative;

    to .thumb ! this makes the overflow:hidden work.. ๐Ÿ™‚ IE7 fix