From our sponsor: Meco is a distraction-free space for reading and discovering newsletters, separate from the inbox.
Today we will create an animated portfolio gallery with jQuery. The gallery will contain a scroller for thumbnails and a content area where we will display details about the portfolio item. The image can be enlarged by clicking on it, making it appear as an overlay.
The idea is to animate the content elements whenever a thumbnail is clicked. We will animate the heading from the top, fade out the previous image and slide the descriptions from the sides.
The great template collection for the demo can be found on DzineBlog.
Let’s start with the HTML structure.
Tiny break: 📬 Want to stay up to date with frontend and trends in web design? Subscribe and get our Collective newsletter twice a tweek.
The Markup
First we will create the structure for the content area. For that we will create a main div element with the class “pg_content”. Inside we will place the main heading with the class and id “pg_title”, the preview container with the id “pg_preview” and the description elements with the class “pg_description”. The description divs will also have an individual class, i.e. “pg_desc1” and “pg_desc2”:
<div class="pg_content"> <div id="pg_title" class="pg_title"> <h1 style="display:block;top:25px;"> Shape Company Website Design </h1> <h1>Summer of Love</h1> ... </div> <div id="pg_preview"> <img class="pg_thumb" style="display:block;z-index:9999;" src="images/medium/1.jpg" alt="images/large/1.jpg"/> <img class="pg_thumb" src="images/medium/2.jpg" alt="images/large/2.jpg"/> ... </div> <div id="pg_desc1" class="pg_description"> <div style="display:block;left:250px;"> <h2>Project Description</h2> <p>A description comes here</p> </div> <div> <h2>Project Description</h2> <p>A description comes here</p> </div> ... </div> <div id="pg_desc2" class="pg_description"> <div style="display:block;left:250px;"> <h2>Technologies Used</h2> <p>A text comes here</p> </div> <div> <h2>Technologies Used</h2> <p>A text comes here</p> </div> ... </div> </div>
All the first elements inside of those containers will have a specific inline style, making them visible when we load the page. The rest of the elements will have their style defined in the CSS, i.e. their position when they are hidden.
The thumbnails scroller will have the following structure (based on Manos Malihu’s thumbnail scroller):
<div id="thumbContainter"> <div id="thumbScroller"> <div class="container"> <div class="content"> <div> <a href="#"> <img src="images/thumbs/1.jpg" alt="" class="thumb" /> </a> </div> </div> <div class="content"> ... </div> ... </div> </div> </div>
And finally, we will add a div for the semi-transparent overlay:
<div id="overlay"></div>
Let’s take a look at the style.
The CSS
We start by resetting the margins and paddings, and by the general body style:
*{ margin:0; padding:0; } body{ background: #564c4c url(../webtreats2.jpg) repeat top left; font-family:"Trebuchet MS","Myriad Pro", Helvetica, sans-serif; font-size:12px; color: #111; overflow-x:hidden; }
This and more beautiful background images can be found on http://webtreats.mysitemyway.com.
The overlay is going to have the following style:
#overlay{ position:fixed; top:0px; left:0px; width:100%; height:100%; background: #000; display:none; opacity:0.9; }
If you want this to work in IE, please add the filter opacity property.
The style for the thumbnail slider will be the following:
#thumbContainter{ position:fixed; top:0px; left:0px; bottom:0px; margin:0; width:175px; padding:0 10px; background:transparent url(../bg.png) repeat top left; border-right:1px solid #f0f0f0; -moz-box-shadow:-2px 0px 10px #000 inset; -webkit-box-shadow:-2px 0px 10px #000 inset; box-shadow:-2px 0px 10px #000 inset; } #thumbScroller{ position:relative; height:600px; overflow:hidden; left:-180px; } #thumbScroller .container{ position:relative; top:0; float:left; } #thumbScroller .content{ clear:both; float:left; } #thumbScroller .content div{ padding:2px; height:100%; float:left; } #thumbScroller .content a{ outline:none; } #thumbScroller img{ border:5px solid #000; -moz-box-shadow:0px 0px 2px #000; -webkit-box-shadow:0px 0px 2px #000; box-shadow:0px 0px 2px #000; }
All the elements in the content area will be placed absolutely:
img.pg_thumb, img#pg_large, .pg_title h1, .pg_content .pg_description div { position:absolute; }
The description divs will be not be displayed initially:
.pg_content .pg_description div{ display:none; }
The main heading will have a black patterned background image, just like the main thumbnail container. The position will be set to the values where the element will not be visible, hence we will have a top of -50px:
.pg_title h1{ display:none; left:250px; top:-50px;/*25*/ background:transparent url(../bg.png) repeat top left; padding:10px 20px; color:#fff; font-weight:bold; }
We will then animate the top to 25px to make the heading visible.
The thumb needs to be hidden, too:
img.pg_thumb{ display:none; }
The large preview of the image will be created when we click on a portfolio item in the content area. It will have the highest z-index:
img#pg_large{ z-index:9999; }
The style of the thumbnail in the content area and the style of the large preview will be as follows:
img.pg_thumb, img#pg_large{ top:90px; left:250px; padding:10px; background:transparent url(../bg.png) repeat top left; cursor:pointer; }
The descriptions and their headlines are going to have the following style:
.pg_description h2{ color:#000; font-size:22px; margin-bottom:10px; background:transparent url(../bg2.png) repeat top left; padding:5px; } .pg_description p{ font-size:14px; width:500px; padding:10px; overflow:hidden; text-shadow:0px 0px 1px #fff; background:transparent url(../bg.png) repeat top left; color:#fff; }
and finally we need to define the positions of the description divs:
#pg_desc1 div{ top:420px; left:205px; } #pg_desc2 div{ top:560px; left:295px; }
And that was the style. Let’s check out the JavaScript next.
The JavaScript
The main idea is to create the scrollable thumbnails container, and to provide the transitions of the content elements. Also, we need to define what happens when we click on a medium image in the content area to view the large image preview.
First, let’s define some variables:
//index of current item var current = 0; //speeds / ease type for animations var fadeSpeed = 400; var animSpeed = 600; var easeType = 'easeOutCirc'; //caching var $thumbScroller = $('#thumbScroller'); var $scrollerContainer = $thumbScroller.find('.container'); var $scrollerContent = $thumbScroller.find('.content'); var $pg_title = $('#pg_title'); var $pg_preview = $('#pg_preview'); var $pg_desc1 = $('#pg_desc1'); var $pg_desc2 = $('#pg_desc2'); var $overlay = $('#overlay'); //number of items var scrollerContentCnt = $scrollerContent.length; var sliderHeight = $(window).height(); //we will store the total height //of the scroller container in this variable var totalContent = 0; //one items height var itemHeight = 0;
Then, we want to create the scrollable thumbnails container, after all its thumbnail images are loaded:
var cnt = 0; $thumbScroller.find('img').each(function(){ var $img = $(this); $('').load(function(){ ++cnt; if(cnt == scrollerContentCnt){ //one items height itemHeight = $thumbScroller.find('.content:first').height(); buildScrollableItems(); //show the scrollable container $thumbScroller.stop().animate({ 'left':'0px' },animSpeed); } }).attr('src',$img.attr('src')); });
When we click on a thumbnail in the scrollable container, we want to display the according content elements. We will use the index of the thumbnail in order to know which title, image and description to show:
$scrollerContent.bind('click',function(e){ var $this = $(this); var idx = $this.index(); //if we click on the one shown then return if(current==idx) return; //if the current image is enlarged, //then we will remove it, but before //we will animate it just like we will do it with the thumb var $pg_large = $('#pg_large'); if($pg_large.length > 0){ $pg_large.animate({ 'left':'350px', 'opacity':'0' },animSpeed,function(){ $pg_large.remove(); }); } //get the current and clicked item's elements var $currentTitle = $pg_title.find('h1:nth-child('+(current+1)+')'); var $nextTitle = $pg_title.find('h1:nth-child('+(idx+1)+')'); var $currentThumb = $pg_preview.find('img.pg_thumb:eq('+current+')'); var $nextThumb = $pg_preview.find('img.pg_thumb:eq('+idx+')'); var $currentDesc1 = $pg_desc1.find('div:nth-child('+(current+1)+')'); var $nextDesc1 = $pg_desc1.find('div:nth-child('+(idx+1)+')'); var $currentDesc2 = $pg_desc2.find('div:nth-child('+(current+1)+')'); var $nextDesc2 = $pg_desc2.find('div:nth-child('+(idx+1)+')'); //the new current is now the index of the clicked scrollable item current = idx; //animate the current title up, //hide it, and animate the next one down $currentTitle.stop().animate({ 'top':'-50px' },animSpeed,function(){ $(this).hide(); $nextTitle.show().stop().animate({ 'top':'25px' },animSpeed); }); //show the next image, //animate the current to the left and fade it out //so that the next one gets visible $nextThumb.show(); $currentThumb.stop().animate({ 'left': '350px', 'opacity':'0' },animSpeed,function(){ $(this).hide().css({ 'left' : '250px', 'opacity' : 1, 'z-index' : 1 }); $nextThumb.css({ 'z-index':9999 }); }); //animate both current descriptions left / right and fade them out //fade in and animate the next ones right / left $currentDesc1.stop().animate({ 'left':'205px', 'opacity':'0' },animSpeed,function(){ $(this).hide(); $nextDesc1.show().stop().animate({ 'left':'250px', 'opacity':'1' },animSpeed); }); $currentDesc2.stop().animate({ 'left':'295px', 'opacity':'0' },animSpeed,function(){ $(this).hide(); $nextDesc2.show().stop().animate({ 'left':'250px', 'opacity':'1' },animSpeed); }); e.preventDefault(); });
When we click on a thumbnail in the content area (the medium picture), it will animate to the size of the large image. Then we will load the large image and insert it after the thumbnail. We just need to hide the thumbnail then, in order to display the large image:
$pg_preview.find('.pg_thumb').bind('click',showLargeImage); //enlarges the thumb function showLargeImage(){ //if theres a large one remove $('#pg_large').remove(); var $thumb = $(this); $thumb.unbind('click'); var large_src = $thumb.attr('alt'); $overlay.fadeIn(200); //animate width to 600px,height to 500px $thumb.stop().animate({ 'width' : '600px', 'height': '500px' },500,function(){ $('').load(function(){ var $largeImg = $(this); $largeImg.insertAfter($thumb).show(); $thumb.hide().css({ 'left' : '250px', 'opacity' : 1, 'z-index' : 1, 'width' : '360px', 'height' : '300px' }); //when we click the large image //we revert the animation $largeImg.bind('click',function(){ $thumb.show(); $overlay.fadeOut(200); $(this).stop().animate({ 'width' : '360px', 'height': '300px' },500,function(){ $(this).remove(); $thumb.css({'z-index' : 9999}); //bind again the click event $thumb.bind('click',showLargeImage); }); }); }).attr('src',large_src); }); }
When we resize the window, the scroller’s height needs to be adapted to the new window height:
$(window).resize(function() { var w_h = $(window).height(); $thumbScroller.css('height',w_h); sliderHeight = w_h; });
And finally, the function for creating the scroller container (adapted from Manos’ script, check it out here: Manos Malihu’s thumbnail scroller)
function buildScrollableItems(){ totalContent = (scrollerContentCnt-1)*itemHeight; $thumbScroller.css('height',sliderHeight) .mousemove(function(e){ if($scrollerContainer.height()>sliderHeight){ var mouseCoords = (e.pageY - this.offsetTop); var mousePercentY = mouseCoords/sliderHeight; var destY = -(((totalContent-(sliderHeight-itemHeight))-sliderHeight)*(mousePercentY)); var thePosA = mouseCoords-destY; var thePosB = destY-mouseCoords; if(mouseCoords==destY) $scrollerContainer.stop(); else if(mouseCoords>destY) $scrollerContainer.stop() .animate({ top: -thePosA }, animSpeed, easeType); else if(mouseCoords
And that’s all! If you want to add some spice by cufonizing the headlines, you can add the following lines to the head of your HTML:
<script src="js/cufon-yui.js" type="text/javascript"></script> <script src="js/Quicksand_Book_400.font.js" type="text/javascript"></script> <script type="text/javascript"> Cufon.replace('h1,h2'); </script>
You can find the beautiful Quicksand and other awesome fonts on www.fontsquirrel.com.
We hope you enjoyed the tutorial and find it useful!
Awesome, very clean javascript code. Love it, great work!
Amazing work, as usual
Keep up the great work
I have downloaded your script but in it Left thumbnail panel not displaying can you check it and give me proper download zip then we appreciate it , bye the way gr8 work thanks for sharing..
@Meera @Catalin I have updated the ZIP file and now it is working! Sorry for that! Thank you all for your great feedback! Cheers, ML
Woowww….
Realy nice work, thnx 4 ur effort
The download package isn’t working.
Great as always…
Clean Jquery code
Nice Html code
Thanks Mary Lou
I am using Chrome and i see basiaclly the same bug i wrote about in one of the other tutorials, full page image gallery tutorial . . .
I can’t believe this is too gud. I like the work may b i’d like to use it on my website.
a little difficult in the right clicking on the scroll boss?
if we click a picture, how do I return again?
awesome job…ty \m/
WOW!
This is so beautifiul!
Another outstanding example of jQuery effect shared with us. Thanks so much!
very nice
Looks great in Chrome and Safari, but Firefox 4.0b7 for mac is looking completely glitched for me.
Anybody else getting this?
Great tutorial though, as usual!
This is so beautifiul!
Awesome…as ever….
Great !
Very good thing…
great as always…..
I noticed that you didn’t have a license anywhere on your code. I’m assuming this is free to use?? (Weird question, I know but I need to ask for work. 🙂 )
Great work by the way.
Thank you all for your great feedback!
@Mike, yes it is free for personal and commercial use, thanks for asking!
This is beautiful
Great Job
Nice, thanks !
Awesome, Awesome, Awesome, Awesome. and Awesome (again :).
I really liked your work.
hi just want to ask if i want to add some more thumails and pages wht i hav to do. Plz if u can let me soon it will be great.
Hey,
Can I just directly use this as an internal static page in my wordpress based website?! A total cipher in web programming…
very very good
tanks
who needs varsity…? ..i got it all here
Really great script! I want to add previous en next buttons can someone help me?
Converted Portfolio in Joomla Version check it http://bit.ly/i0S6kM
Hey Mary Lou,
Your Blog is My Design Inspiration ^_^
Like This ^_^
Converted Animated Portfolio Gallery with jQuery to Blogger »»» http://assadesign.blogspot.com/
thanks for sharing this nice tutorial it is more helpful to all keep sharing
i have started to do this portfolio.. so many doubt
This gallery is working fine and very good.But in IE7 & IE8 it is not working perfectly.there is no smooth easing.
Please help me with this problem.
Thanks in advance.
Its beautiful !! Congratz ! But, its too slow on IE7. Incredibly on ie6 its Ok, but on ie7 its almost stopping.
Hello Paulo,
maybe it’s a problem with Cufón, you can try and remove the scripts from the head. Let me know if it get’s better, hope it helps, cheers, ML
Beautiful, but do not work in IE9
Hello Mary,
I think the problem occurred because im running it local. I’ve tried remove the Cufon and nothing changed. And again, congratz about your website.
i love this portfolio layout!
my question is this:
instead of changing a single image when each thumbnail in the vertical scroller is clicked, would it be possible to change a horizontal scroller for each project?
i would love to use this on my portfolio site, but would like to exhibit multiple images for each project.
any suggestions?
stunning… really nice.. but I’m also wondering on how you can make this into a horizontal scroller?
Good Job
Mary Lou i love this gallery, thanks so much! Keep up the great work!
Beautiful portfolio, but its almost stopping in IE8… I try remove the scripts from the head, but nothing changed.. Please, somebody, help me with this problem!
and how can i put the thubs sliders on bottom with a horizontal scroller? With manos code its easy, but in this compilation i didnt found…
how do i show more thumbnails…i wrote all the list in the inside of the code, but it only shows 8 thumbnails…HELP plis
It is very good,I like it
Awesome job!
I made some modifications and used on my website, check it out: http://www.patriciaparrela.com.
Thanks a lot 🙂
When I tired to add more images, the side bar disrepair, what am I doing wrong?
I added the image urls to 3 locations on the html page.
Is any editing needed on the .js files?
First of all I have to say thank you Mary for your free work sharing with the world! 🙂
And for all of you people as you probably noticed it doesn’t work in IE9. Well here is solution… just chance cufon-yui.js file with this one and then will work just fine also in IE9. Mary used 1.09 and here you have newer version 1.09i to solve the problem!
http://cufon.shoqolate.com/js/cufon-yui.js?v=1.09i
Be cool people! 😉
Hi,
I’m trying to add on more thumbnails on the side bar, but when adding more, the entire bar no longer shows.
Do I have to edit any other files other then the html? Would I need to edit the javascript files as well?
Interesting solution for portfolio
Thnaks
I really like the gallery and was wondering if there is a way to make the thumbnails scrollable with the mousewheel?
Without showing the scoll (e.g. not overflow:scroll)
very nice! But how to reduce the scroll speed of scrolling?