Thumbnails Navigation Gallery with jQuery

In this tutorial we are going to create an extraordinary gallery with scrollable thumbnails that slide out from a navigation. We are going to use jQuery and some CSS3 properties […]

In this tutorial we are going to create an extraordinary gallery with scrollable thumbnails that slide out from a navigation. We are going to use jQuery and some CSS3 properties for the style. The main idea is to have a menu of albums where each item will reveal a horizontal bar with thumbnails when clicked. The thumbnails container will scroll automatically when the user moves the mouse to the left or right.

When a thumbnail is clicked it will be loaded as a full image preview in the background of the page. We will also have a text container for one of the menu items.

The beautiful photos are from Mark Sebastian’s photostream on Flickr. You can find all the images used in the demo in the set The “IT” Factor. Please review the Creative Commons license that is included in the demo.

So, let’s get started!

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

Our HTML is mainly going to consist of a wrapper and the menu list. We will have some other elements, like the full image, the loading div and the halftone overlay. First, let’s create the wrapper:

<div id="st_main" class="st_main">

</div>

Inside of our wrapper we will add the following:

<img src="images/album/1.jpg" alt="" class="st_preview" style="display:none;"/>

<div class="st_overlay"></div>

<h1>Mark Sebastian</h1>

<div id="st_loading" class="st_loading">
	<span>Loading...</span>
</div>

The first element is our full preview image. The overlay is going to be a fixed div which will stretch over the whole screen repeating a halftone pattern to create a fancy overlay effect on the image. We also add a title and a loading div.

We then add an unordered list where each li element is going to contain a span for its title and the thumbnails wrapper. The last li element is going to contain some wrapper for text, that’s why we will not give it the class “album”. Later, in the jQuery function we will need to distinguish that.

<ul id="st_nav" class="st_navigation">
	<li class="album">
		<span class="st_link">
			Newest Collection
			<span class="st_arrow_down"></span>
		</span>
		<div class="st_wrapper st_thumbs_wrapper">
			<div class="st_thumbs">
				<img src="images/album/thumbs/1.jpg" alt="images/album/1.jpg"/>
				<img src="images/album/thumbs/2.jpg" alt="images/album/2.jpg"/>
				...
			</div>
		</div>
	</li>
	...
	<li>
		<span class="st_link">
			About
			<span class="st_arrow_down"></span>
		</span>
		<div class="st_about st_thumbs_wrapper">
			<div class="st_subcontent">
				<p>
					Some description
				</p>
			</div>
		</div>
	</li>
</ul>

The thumbnail images get the alt value of the path to the full size image. That might not be the proper use of the alt attribute, but it’s just so convenient for our functionality that we will use it this way.

Let’s take a look at the style.

The CSS

First, let’s reset the paddings and margins for all elements and define the general styles:

*{
	margin:0;
	padding:0;
}
body{
	font-family:"Myriad Pro","Trebuchet MS", Helvetica, sans-serif;
	font-size:16px;
	color:#fff;
	background-color:#000;
	overflow:hidden;
}
h1{
	margin:20px;
	font-size:40px;
}

Making the body overflow hidden we avoid any scroll bar appearing, but you can adapt that to your needs. I.e. if it is important that the full sized image is completely viewable by the user, you might want to remove the overflow:hidden property.

Next, we will define the style for the full size image, the overlay and the loading div:

.st_main img.st_preview{
	position:absolute;
	left:0px;
	top:0px;
	width:100%;
}
.st_overlay{
	width:100%;
	height:100%;
	position:fixed;
	top:0px;
	left:0px;
	background:transparent url(../images/pattern.png) repeat-x bottom left;
	opacity:0.3;
}
.st_loading{
	position:fixed;
	top:10px;
	right:0px;
	background:#000 url(../images/icons/loader.gif) no-repeat 10px 50%;
	padding:15px 40px 15px 60px;
	-moz-box-shadow:0px 0px 2px #000;
	-webkit-box-shadow:0px 0px 2px #000;
	box-shadow:0px 0px 2px #000;
	opacity:0.6;
}

By setting the image width to be always 100%, we make sure that it occupies all the horizontal space on the page. For very large screens the image might look pixelated which can, of course, be avoided by using gigantic images. In our demo we use a maximum width of 1600 pixel to make the loading time bearable. The halftone pattern on top of the image helps a little to disguise a pixelated effect.

Please note that whenever opacity is used, the IE filter property needs to be used if you want to achieve semi-transparent effects in IE. The overlay looks like crap if you use the filter property, though. Check out the ZIP file, I added the IE DXImageTransform filter to the respective styles.

The navigation will be positioned absolutely:

ul.st_navigation{
	position:absolute;
	width:100%;
	top:140px;
	left:-300px;
	list-style:none;
}

The initial left value is set to -300 pixel because we want to slide it in only after our full image is loaded. If you use longer titles in the list items, you might need to adapt this value.

Our list elements are going to have the following style:

ul.st_navigation li {
	float:left;
	clear:both;
	margin-bottom:8px;
	position:relative;
	width:100%;
}

The span for the title will be styled as follows:

ul.st_navigation li span.st_link{
	background-color:#000;
	float:left;
	position:relative;
	line-height:50px;
	padding:0px 20px;
	-moz-box-shadow:0px 0px 2px #000;
	-webkit-box-shadow:0px 0px 2px #000;
	box-shadow:0px 0px 2px #000;
}

Next, we define the style for the spans with the up/down arrow for opening and closing the thumbnail container:

ul.st_navigation li span.st_arrow_down,
ul.st_navigation li span.st_arrow_up{
	position:absolute;
	margin-left:15px;
	width:40px;
	height:50px;
	cursor:pointer;
	-moz-box-shadow:0px 0px 2px #000;
	-webkit-box-shadow:0px 0px 2px #000;
	box-shadow:0px 0px 2px #000;
}
ul.st_navigation li span.st_arrow_down{
	background:#000 url(../images/icons/down.png) no-repeat center center;
}
ul.st_navigation li span.st_arrow_up{
	background:#000 url(../images/icons/up.png) no-repeat center center;
}

The wrapper for the thumbnail container will be positioned absolutely and we want to hide any vertical overflow:

.st_wrapper{
	display:none;
	position: absolute;
    width:100%;
    height:126px;
    overflow-y:hidden;
	top:50px;
    left:0px;
}

Although the thumbs are only 120 pixels high, we want to leave some space so that the box shadow of the images inside will not be cut away.
The thumbnails container will simply be styled as follows:

.st_thumbs{
    height:126px;
    margin: 0;
}

The thumbnails will have a neat box shadow and some spacing:

.st_thumbs img{
    float:left;
    margin:3px 3px 0px 0px;
    cursor:pointer;
	-moz-box-shadow:1px 1px 5px #000;
	-webkit-box-shadow:1px 1px 5px #000;
	box-shadow:1px 1px 5px #000;
	opacity:0.7;
}

The st_about class is the wrapper class for the text container:

.st_about{
	display:none;
	position:absolute;
	top:50px;
    left:0px;
	opacity:0.6;
}

And, finally the text container itself:

.st_subcontent{
	background:#000;
	padding:30px;
	-moz-box-shadow:0px 0px 10px #000;
	-webkit-box-shadow:0px 0px 10px #000;
	box-shadow:0px 0px 10px #000;
}

And that’s all the style! Let’s make some magic!

The JavaScript

In our jQuery function we will first define some variables:

//the loading image
var $loader		= $('#st_loading');
//the ul element
var $list		= $('#st_nav');
//the current image being shown
var $currImage 	= $('#st_main').children('img:first');

The first thing that we want to do is to load the current full size image. After it’s loaded, we want the navigation to appear:

$('<img>').load(function(){
	$loader.hide();
	$currImage.fadeIn(3000);
	//slide out the menu
	setTimeout(function(){
		$list.animate({'left':'0px'},500);
	},
	1000);
}).attr('src',$currImage.attr('src'));

The buildThumbs() function calculates the widths of all the thumbnail containers. We need that value for the automatic scrolling function later on:

buildThumbs();

function buildThumbs(){
	$list.children('li.album').each(function(){
		var $elem 			= $(this);
		var $thumbs_wrapper = $elem.find('.st_thumbs_wrapper');
		var $thumbs 		= $thumbs_wrapper.children(':first');
		//each thumb has 180px and we add 3 of margin
		var finalW 			= $thumbs.find('img').length * 183;
		$thumbs.css('width',finalW + 'px');
		//make this element scrollable
		makeScrollable($thumbs_wrapper,$thumbs);
	});
}

Next, we define the behavior of clicking on the arrows. If it’s down, we will expand the thumbnail container and hide any other. If it’s up, we will make the current container hide again.

$list.find('.st_arrow_down').live('click',function(){
	var $this = $(this);
	hideThumbs();
	$this.addClass('st_arrow_up').removeClass('st_arrow_down');
	var $elem = $this.closest('li');
	$elem.addClass('current').animate({'height':'170px'},200);
	var $thumbs_wrapper = $this.parent().next();
	$thumbs_wrapper.show(200);
});
$list.find('.st_arrow_up').live('click',function(){
	var $this = $(this);
	$this.addClass('st_arrow_down').removeClass('st_arrow_up');
	hideThumbs();
});

Before we define the hideThumbs() function, we specify what happens when clicking on a thumb. The full size image will show and while it’s loading we will make the loading div appear. Then we animate the opacity and fade the image in:

$list.find('.st_thumbs img').bind('click',function(){
	var $this = $(this);
	$loader.show();
	$('<img class="st_preview"/>').load(function(){
		var $this = $(this);
		var $currImage = $('#st_main').children('img:first');
		$this.insertBefore($currImage);
		$loader.hide();
		$currImage.fadeOut(2000,function(){
			$(this).remove();
		});
	}).attr('src',$this.attr('alt'));
}).bind('mouseenter',function(){
	$(this).stop().animate({'opacity':'1'});
}).bind('mouseleave',function(){
	$(this).stop().animate({'opacity':'0.7'});
});

The function to hide the thumbnails looks as follows:

function hideThumbs(){
	$list.find('li.current')
		 .animate({'height':'50px'},400,function(){
			$(this).removeClass('current');
		 })
		 .find('.st_thumbs_wrapper')
		 .hide(200)
		 .andSelf()
		 .find('.st_link span')
		 .addClass('st_arrow_down')
		 .removeClass('st_arrow_up');
}

We animate the height of the li and make the thumbnails container disappear like that. We also need to set the class for the arrow span correctly.

And finally, we will define the makeScrollable() function that automatically scrolls the thumbnails div horizontally on mouse move:

function makeScrollable($outer, $inner){
	var extra 			= 800;
	//Get menu width
	var divWidth = $outer.width();
	//Remove scrollbars
	$outer.css({
		overflow: 'hidden'
	});
	//Find last image in container
	var lastElem = $inner.find('img:last');
	$outer.scrollLeft(0);
	//When user move mouse over menu
	$outer.unbind('mousemove').bind('mousemove',function(e){
		var containerWidth = lastElem[0].offsetLeft + lastElem.outerWidth() + 2*extra;
		var left = (e.pageX - $outer.offset().left) * (containerWidth-divWidth) / divWidth - extra;
		$outer.scrollLeft(left);
	});
}

For cufonizing the titles and adding some decent shadow, we will include the following into the head of our html document:

<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('span,p,h1',{
		textShadow: '0px 0px 1px #ffffff'
	});
</script>

And that’s it! We hope you enjoyed the tutorial and find it useful!

Message from TestkingWe offer exceptional 220-702 training program to help you pass sun certification in easy and fast way. Complete your CISSP certification within days using certified resources.

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 in the loop: Get your dose of frontend twice a week

Fresh news, inspo, code demos, and UI animations—zero fluff, all quality. Make your Mondays and Thursdays creative!

Feedback 249

Comments are closed.
  1. Hi,
    I’d like that the filmstrip with all the category’s photos dissapears automatically, with no user interaction. It’s that possible? Thanks

  2. Hi Mary Lou,

    I try again asking for the many “warnings” I get in the firefox error console (for css and javascript ) if I look at your demo for the navigation gallery.

    maxx

  3. Hi,
    I have got one problem. I’ve made my galery which is based on your tutorial. It works perfectly on PC, but when I putted it on a server it doesnt work. What may be the solution of this trouble?
    Peter

  4. Is there a way of adding some text and a link to, say , a website url for each image?

  5. Hi,
    I see a little problem with this gallery on Firefox and IE. When I open demo in Firefox everything works but very slowly. Transformation from one picture to another isn’t fluent. The same on IE. Is there any solution for the issue?

  6. Thaks for the free download.. i am going to download this for my new website portfolio…

  7. Thank you Mary! This gallery is just awesome.

    Is there any way I could add a button to show/collapse the whole menu?

    Thanks!
    Chris

  8. I think this script is beautiful. I just had one quick question, how would i implement captions? Thanks

    • Thank you for your comment, Jorge. I believe it had to do with using Cufón! I have updated the JS file and it seems to work fine now. Cheers, ML

  9. Mary, I think you must review all your scripts, because I see that your script 3D Wall Gallery don’t work too.

  10. Mary, you update the JS file on Demo but not on the Download script, that don’t work yet.
    Regards

  11. so, the gallery is ready .. the images are now not dynamically retrieved from a directory but static. but it is a results 🙂
    I have the background yet made scrollable, so that vertical images can be shown better and I have the opacity adjusted of the menu and the thumbs. Now I’ll trying the buttons (and the functionality) to navigate prev and next.

    who wants to see more:

    http://www.jensposer.de/showcase3.php

  12. Thanks you a lot for your work. Made me inspired.
    Take a look on the side builded under inspiration of your script (slightly rewrited tbh, but core and idea is still yorus)
    http://semeynoefoto.com
    Still a lot to polish but site itself already selling.

  13. Just wanted to say – Great Work Mary, for the complete site. 🙂
    I keep bumping into your site every now and go back with fresh ideas.

    for the above example, i wish there was dynamic fetching of the images and thumbs from folder instead of inserting images individually via html. also, wish we could integrate a download button somewhere (to download the large bg image in display).
    so i had to go with:
    http://tympanus.net/Tutorials/FreshSlidingThumbnailsGallery/
    though this one was more suited for my site.

    anyways, thanks for all the code. hope the licensing is still free. wheres the donate button?! 🙂

  14. Awesome layout/composition Mary. Seems like it could be used very nicely with a stretched out background video too.

  15. I checked this post for slideshow.. but the ladies floored me! Awesome slideshow does it work! :B 😀

  16. Nice idea, looks great..
    but yeah, thumbs hide parts of the image and I dislike the concept of missing prev/next buttons.

  17. One question! I am just a designer and I am asking from a design point of view, so please excuse if I sound stupid.
    How did you manage to re-size the photo as I lowered the browser window. Most of the site who has used your code shows the images stretch here and there thereby looking awkward. What is the optimum size for those background images? Do you control it by code as they lower it?
    By the way GREAT Tutorial!

  18. Amazing ! really nice

    really nice
    I have a question, how do I make one of menu items to open automatically when the site is loaded?
    for example:
    load image
    load nav
    Automatically open first menu item

    Thanks for Everything!

  19. Hi Mary, your work is amazing!

    One question, and if anyone knows and would kindly like to help it’ll be very much appreciated!!

    I’d like to display some description of each photo…by having either a popup or sliding panel when the full size image is loaded..any idea how, please?

  20. Is there a way to merge lightbox and this jquery gallery?

    theres a conflict between the prototype.js that lightbox provides and the 1.4.2.

    anyone ever find a work around?

    thanks!

  21. Mary Lou can I have a link to show or hide only one strip on the bottom of the page???

    thanks

  22. Fantastic tut… I like and will use your ideas. However, I just moved from IE8 to IE9 and the menu does not work properly anymore (text does not render). Thanks much — hawk182

  23. Hi Mary Lou,

    Can you please tell me how to add a link and description to the background image? I am a designer and I don’t really understand the js.

    Appreciate this tutorial.

    best regards,
    Zoe

  24. Hello Mary,

    This is awesome. Thanks for you sharing.
    I need some help. The menu doesn’t scroll in IE6. I need to fix that. Can you help me?

    Thanks a lot.

  25. It’s AMAZING !!!

    Mary Lou i really admire you: you have talent, creativity and a wonderful taste.

    Please let us know how to implement caption of text over the image !!!

  26. It would be ideal that once an image is selected that the menu no longer obtrudes over it, blocking the view. I realize the user can “close” the menu, but this is not ideal.

    How would this be accomplished?

  27. Looks absolutely epic in Firefox, but the menus get messed up in Internet Explorer 9. How can I fix this?

  28. Looks absolutely epic in Firefox, but the menus get messed up in Internet Explorer 9. How can I fix this?

    ?e 9 dont working !
    Please fix.

  29. @ Admin I want to add multiple pics from the database i mean i want to make it dynamic image gallery for this purpose what i have to do?

  30. This is just perfect for me, the only thing is that its cant show portraits that well. it seems like its scales on the width in the background image.

  31. Texts on h1 and span class=”st_link” aren’t appearing.
    Could tell me why?

    please email me.

    thanks

  32. Looks absolutely epic in Firefox and google chrome too, but the menus and title get messed up in Internet Explorer 9. How can I fix this?

  33. Really great!!!!!!
    just a question….how can I mahe the thumbs heighter ? I tried everything!!
    thanks!!!!!!

  34. Hi, Thank you for you tutorial.
    Is it possible to add a description for any image???
    Thank a lot
    Luca

  35. Hi! Love this thing!
    I tried to implement it on my web site and when I preview it locally works like a charm BUT when i upload to server I get some menu links background glitch… Can you PLEASE help me with this…
    thx

    • @mmartinovich Looks really great! But I don’t see any glitch? Did you solve the problem? You have the loader.gif missing and it’s giving an error in Chrome… Cheers, ML

  36. Hi,

    It’s a really great job, congratulations!

    I wonder if there’s a way to show captions with each photo.

    Thanks!

  37. Mary Lou, I need you!!! Please, is it possible to add a description for any image…
    Thanks Thanks Thanks Thanks

  38. Please Mary….i tried for weeks and nothing!!
    Is it possible to link to a lightbox from the thumbs? Meaning that there is a fixed background image, but the thumbnails open up in a lightbox?
    PLEASE HELP ME… THANKS

  39. Amazing script and great design.

    I am wondering if Mary Lou or someone can help me in getting the menu items to display horizontally rather than vertically?

    Thanks