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!

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.

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

👾 Hey! Looking for the latest in frontend? Twice a week, we'll deliver the freshest frontend news, website inspo, cool code demos, videos and UI animations right to your inbox.

Zero fluff, all quality, to make your Mondays and Thursdays more creative!

Feedback 249

Comments are closed.
  1. Hello, excellent work, I have a question that has not been resolved here.
    As you can do to make the thumbnails disappear when you click one of them.
    Greetings.

  2. Hi Mary Lou,

    beautiful work!!! Amazing result…thank you so much for sharing this with us.

    @BrunoAxhausen Thank you for sharing the script that allows to collapse (auto-close) the thumbs once they are clicked.

  3. Hi – i’m trying to get this working in an asp.net (framework 4) the page has a master site page.

    Struggling to get it past the loading stage (black background with moving icon is as far as i can get)

    Any pointers welcome please

    Thanks

  4. HI Mary Lou, great tutorial , i put hideThumbs(); on line 211 to close the thumbs when clicked, but i can’t find how to put the navigation for the big img (prev/next button) can you help me and other one who asked it?
    thanks!!!!

    bye from Italy

  5. Hi,
    how make visible in text the special caracters? dont work “ç, á, é, í, ó, ú” and im do a brazilian site (br).

    Can anybody helpme?
    twitter: @viniciuskran


    Thanks!

  6. hello i´m trying to load my images in sfw instead jpg to protect them, but the swf don´t load in the page like jpg , is there any way to make it work?

    please help, thank you

  7. is there a way to make thumbnails disappear when you click one of them or when you click anywhere outside in the body.

    Thank you very much

  8. Hi REGEN, i put
    hideThumbs();
    on line 211 to close the thumbs when clicked,. hope that helps you.. bye

  9. Amazing work Mary!
    Just one quick question. I would like one gallery to be open when the website loads. could you please let me know how I can do this? Tried a lot but to no avail. Appreciate your help. Thanks.

  10. Fantastic tutorial and implementation, Mary Lou. Enables a jQuery amateur like me to create a custom gallery.

    I have one problem, though: my thumbnail tray’s vertical axis, so to speak, is on my very first thumbnail. Whenever I move the pointer beyond the center of the first thumbnail, the tray scrolls all the way to the right. Surely, the axis is supposed to be in the middle of the thumbnail tray.

    http://thesoundofspiders.net/craig/collections.html

    If anyone can help, it’d be greatly appreciated. Keep up the good work!

    DanielT

  11. Hi

    I am a freelance web developer. I recently had to implement a gallery plugin and this works beautifully. I modified the CSS a bit to get it to fit into the template I was using instead of having it full screen. Everything works except there’s a ghost image that appears briefly below the gallery when you click on a thumbnail. I’m not sure if this is part of the transition effect but is there any way to hide it?

    http://mschf.net/stonevalley/gallery.html to see what I am talking about. Any help would be greatly appreciated. Thank you! Wonderful tutorial.

  12. update … must have been my error. it works fine now after starting over from the beginning.

  13. Does anyone know how to attach a link to the larger version on the images? The css {background:url(www.google.com/);} class does not seem to apply as it’s not technically a ‘background image’

  14. Hi Mary-Lou,

    I used some elements of your tutorial to build this website for a client:

    http://www.kenyabeds.com

    They wanted a funky, visual, grungy feel for a backpacking site, and I think this does the trick. Your overlay, animation, and treatment of backgrounds was the inspiration and basis to put this together. Thank you, and I’ve credited codrops on the strapline. Brian.

  15. hi there..

    what an awesome script!

    how do you get it to show automatically the thumbnails when you view the page, without having to click on “best shots” ?

    also, any idea how to have the big image change every few seconds?
    like the next one sliding in from the right?

    Thanks in advance!
    i dont understand all the javascript 🙁

  16. Really nice work Mari Lou!

    I’m wondering how you can change the thumbnail navigation from where it is to the bottom of the page just like your Full Page Image Gallery.

    I’d like the thumbnail to block less the background image.

    I worked with opacity and :hover but it isn’t enough for me.

    Thx !

  17. Dear Mary Lou,
    These all development jquery effects with css you made are extremely unconventional. I wanna thank you so much for giving us a wide opportunity to use this effects in my website… 🙂 Thanks!

  18. I’m so in love with this gallery!! Thank you ML, you are awesome 🙂 I also wanted to know if there is any way of changing the script so that the first album opens automatically when the page loads. Any help is appreciated. Thanks in advance!!

  19. If you want to have a choice between a video or an image change this line of code:

    $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();
    });

    To this:

    $list.find(‘.st_thumbs img’).bind(‘click’,function(){
    var $this = $(this);
    $loader.show();
    var src = $this.attr(‘alt’);
    if (/\.(mp4|ogv)$/i.test(src)) {
    // Create video element here
    }
    else {
    $(”).load(function(){
    var $this = $(this);
    var $currImage = $(‘#st_main’).children(‘img,video’).first();
    $this.insertBefore($currImage);
    $loader.hide();
    $currImage.fadeOut(2000,function(){
    $(this).remove();
    });
    }).attr(‘src’,src);
    }
    });

  20. @Chris. I keep getting a syntax error. if i have a video on youtube, how can i get this into the menu?

    also, how can I get vertical taken pictures to not resize

  21. ok. figured out the vertical thing. you just have to take the 100% off width. although you won’t have it full screen. but… i’d really like to get video on my website for my reel.

  22. how do you make it so you can click the entire menu item? not just the up/down arrows.

    thanks,

    sam

  23. very cool…thanks.
    im trying to put the thumbs navigation bar inside a tab navigation menu. The first tab works great…But the second wont scroll auto (i can see all my thumb only with scrollbar) i think its the var whos fill by the first… this is my test site http://www.ma117.info/testx/tab2.html
    Any idea
    Thanks

  24. Hello,

    I’m a novice web designer and I’m wondering if it’st possible to just use 1 slider strip on a page with a specific width for the slider.

    http://mschf.net/stonevalley/gallery.html

    The above web site has what I’m trying to do, but his sliders if you scroll all the way to the right there is blank space, the slider doesn’t stop at the right of the last picture.

    Also, I think this has been asked, but is it possible to slightly enlarge a thumbnail on mouse over and remove the on click effect?

    Thank you, and any help will be greatly appreciated

  25. Hi Mary Lou, great great tutorial, can you explain me why variable extra is 800px, i can’t understand.

    thank you so much

  26. Hi, in the first I need to say, amazing job your´s.
    Well, in this case, let´s imagine something. I don´t want put image name in the code, I want that, he take all images in the folder and sub folder like that images/gallery1
    and he takes the comments of image in the Data Base as SQL ? How can I do that ?
    Because in Slider Gallery we need put name after name of the image, and if we can just sign the folder can be more easy ? Thanks to all…

  27. @MAX
    The extra 800px is the offset you give to your mouse cursor to make the thumb scroll. set it to zero and the thumb will move as soon your mouse be over… from the side…
    At 800px you can mouve over the first two thumb before the whole Div scroll

  28. Dear Mary Lou,
    I love this tutorial and all the others you have on your site. Thank you for taking the time to post these. I am having some issues with the Thumbnails Navigation Gallery with jQuery. The background seems to work fine in firefox but not in any other browsers, it will not show up. If you have any suggestions please let me know. I am pulling my hair out trying to figure this out.
    Thanks

  29. Does anyone know how to make the arrows on the navigation menu change color when you rollover them?

  30. Hey there,

    This seems like a great tutorial and seems to work fine but on an ipad this demo fails big time.
    Works in landscape but vertical doesnt stretch the height to full the screen.
    Thumbnails dont work either, I choose a thumbnail and it chooses an entirely different image and slides the thumbs to a different set, I can’t seem to select the image I want 99% of the time.
    I can’t swipe through each set of thumbnails so there’s no way to get to the last one.

    It got quite frustrating in the end and I may have to give up on using this for the project I had in mind unless some fixes can be done.

  31. I’m trying to make a catalog and I need to put a product number for each photo.

    I have made somechanges as:

    In style.css

    I have copied .st_loading as .st_product number

    In index.html

    AY02SD4A54DSAA

    AY34938423243AA

    And I have copied $loader as $productnumber

    But When I open the web page,i see all product numbers have written on eachother 🙁

    Can someone please help me?
    ayberkc@hotmail.com

  32. I’m using this codes for making my own boutique catalog.

    Can somebody please help me to add a description (product number) (10-15 character) layer to any photo.

    For example: “Product Code: A338249384” under “.st_loading”

    ayberkc@hotmail.com

    Thank you so much!

  33. Hi, I was just wondering… Is this only for tutorial purposes or is it ok to upload your own work and use this as as portfolio template?

  34. Hi there, great work, i´m using it for a website. Just got one question. is there a way to add a description over the image? i would really appreciate it if you could help me out.
    Thanks

  35. @DenisD
    Thanks for the example, i took a look at it. I changed a few things. actually i don´t need the code on each thumb just a description to appear over the image… and IT´S ALIVE NOW!!
    thanks for the support

  36. Hi, I was wondering how to solve the problem when the browser width is down-sized & the background image collapses, not everyone has a widescreen display

    thanks

  37. Great coding and functionality, I like it’s simplicity. Many thanks to Mary Lou for this. My question is how to remove shadow effect from text. Even if I edit code and set all values to “0” it is still there. And how to change text color separately. Thanks for answer.

  38. Hi,
    This is just plain awesome!
    My query was: I have 68 images to be added into a single album and the scrolling of the thumbnail gallery stops and doesn’t scroll beyond 10th image. How can i make it to auto scroll till last image?

  39. @CARVER: Shadow on which text, i dont see shadow on menu and on the about text either??? Be more specific. Which browser and version do you surf.

    @KAUSBUTH: There something you’v change somewhere else, because if you take original and duplicate the galery block many time like to 68, the autoscroll still work. If it stop a the 10th, then check your galery code block at the 11th, maybe a syntax mistake. Mine work to 63.

  40. Line of code refering to shadow, it is at the beggining of code.

    type=”text/javascript”>
    Cufon.replace(‘span,p,h1’,{
    textShadow: ‘0px 0px 1px #ffffff’

    If you change color to black or remove line all text get this “inner shadow look” like the on in photoshop.

    It would be nice also to change color of text on navigation buttons?

    Firefox 8.0.1

  41. @CARVER…ok i see.
    First delete the shadow command only:Cufon.replace(‘span,p,h1’,{
    });

    You see between braket (….h1) refer to css h1 text formating…

    open the css file, the 3rd element his the h1 formating. just add color: #____. like this
    h1{
    margin:20px;
    font-size:40px;
    color:#58FF3E;
    }

    To change the color of menu text put again in css file at the block
    ul.st_navigation li span.st_link…color:#3642E3;
    But by the way the menu was built…its gone be same color for each menu

    Hope its gone help you