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. I COULD NOT RESIST THE TEMPTATION OF A NEW COMMENT, ´CAUSE I THINK THIS IS ONE OF THE MOST BEAUTIFUL GALLERIES I´VE EVER SEEN IN THE NET AND BELIEVE ME, I ´VE SEEN THOUSANDS OF WEB PAGES

    • @Xtence That’s really great! And you don’t have to credit anyone, thank you for asking! Cheers, ML

  2. Is there a way to have a static background and let the thumbs open in a lightbox (or something similar)? I really love this, but I would rather have a thumb to box way and more control if I want the image to load in the background. Thanks in advance!

  3. hi, great work guys:) One question, please help! How do I add an image logo that doesn’t fade away on a load of the page?

  4. @Nadya If you add something outside and after the st_main div and set it absolute or fixed, it should always stay on top. Hope it helps, cheers, ML

  5. I was just telling my friends, this site is awesome! I’ve learned so much:) Still having troubles….could anyone please, please tell me what controls the navigation to slide down when it’s pressed? I moved things around so that when I press the nav arrow a window (about section for example) appears right to the nav list. How do I stop navigation from moving (empty space below each list item). Thank you so much in advance! Great site and great tutorials.

  6. @Anna, check line 215 in the index html file. There we say that the li will animate to a height of 170px. Maybe you need to change that value. Do you have it online somewhere? I could take a look. Hope it helps, ML

  7. not yet online….locally current, but you did help, tnx, I think I made it work. Thank you so much.

  8. Great work and tutorial, thank you!

    I’m a beginner… how can I ‘auto-close’ the thumbnails after click on one of them?

  9. wow, that is awesome.
    even a noob like me knows how to implement this gallery.

    quick question – is it possible to get rid of the “tiles”/”dark cube” effect?

    Awesome stuff Mary Lou!

  10. Hi, is there any way to start a slideshow in the background after the navigation list is loaded? Kicking in the dark here:)

  11. @Alon just remove the div with the class st_overlay from the html (delete line 43).

    @Thomas you could try and put a link element around the image (line 42).

    @Anna you could check out this post to see how to create a slideshow and apply it to this gallery. You have to iterate through a set of pictures.

    Hope it helps a little, cheers to all,
    ML

  12. Curiosity is there a way to add description and title to each picture and also create sub menu on each navigation??

    • Hey Xtence, it really looks amazing! We are really glad that you could make use of this and it’s very very nice of you to mention us on the page! Thank you and many cheers! ML

  13. Help me..MARY LOU!

    I want thumbnails to go from top to bottom instead of going from left to right….and I also want to leave the thumbnail dialog box open when the website opens ..as I am just using only one navigation tab with 10 different thumbnails…

  14. This design is fabulous. The scrolling nav bar of images is great but it would be great if the nav bar automatically collapsed after an image is selected for viewing.

    It took me a min to realize that all i had to do was click the down arrow to make the scrolling images bar collapse. How automating this function after a user clicks to view an image? How can the code be updated to make this functionality happen?

  15. I have figure out most of the things but I would hope that you can help me with creating submenu…or could guide me at the right directions…:(

  16. Great! 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?

  17. something you should know…your website menus looks all weird on IE 9.0 U NEED TO REALLY CHECK THIS!

  18. Hi Mary Lou,

    thanks so much for this! I’d love to use this for my portfolio website. One issue I face is with image navigation.

    I’d love to add 2 buttons to jump to the next (or previous) image without opening the thumbnail bar. Sadly I have no idea how to do that (or if it’s even possible..). Could you -or anyone else- give me a hint how to do that? Any help would be greatly appreciated!

    Thanks for your help and for making this gallery available!!
    All the best
    Bruno

    @Sai-En I had the same problem. A friend helped me out:

    Add hideThumbs(); to the Script in the indexhtml:

    //clicking on a thumb, replaces the large image
    $list.find(‘.st_thumbs img’).bind(‘click’,function(){
    var $this = $(this);
    $loader.show();
    $(”).load(function(){
    var $this = $(this);
    var $currImage = $(‘#st_main’).children(‘img:first’);
    $this.insertBefore($currImage);
    $loader.hide();
    $currImage.fadeOut(2000,function(){
    $(this).remove();
    });
    hideThumbs();
    }).attr(‘src’,$this.attr(‘alt’));
    }).bind(‘mouseenter’,function(){
    $(this).stop().animate({‘opacity’:’1′});
    }).bind(‘mouseleave’,function(){
    $(this).stop().animate({‘opacity’:’0.7′});
    });

  19. Hi,

    IS there a way you can autostart a scroll for the images and is it possible to add flash as a background?

    Cheers

  20. thanks for this awesome tutorial, but i’ve got a small problem, maybe it’s matter of changing a value but i can’t figure it out.

    I’ve created a navigation bar on top of everything this navbar use jquery superfish to display a submenu but i can’t use the submenu when i move the mouse into the submenu it disappear and i can’t click anything…

    someone has a solution ?

  21. I love this script. Easy to use and modify.

    One thing I have been trying to tweak is when you have multiple li class=”album” is there a way to have the first image in that list to show up when you click on the arrow?

  22. Awsome script! Congratulations. But have anyone figure out how to add a next / previous button to improve the naviagation? I would die for it!

    Thanks!

    Valdecir
    São Paulo, Brazil

  23. I like this exiting Script very much!

    If I try this demo in Firefox (with web developer toolbar) I get there many many “warnings” for JavaScript!?

    Is there something wrong?

    Thanks!

  24. @MSNFC your steps worked except for the load.

    b) Edit “index.html” and add “FullScreenBackground(this);” inside “(img) load.()” function (loads 1st image) right after the “setTimeout” function.

    That step did not work for me but I found adding
    -> FullScreenBackground(‘.st_main img.st_preview’);
    -> FullScreenBackground(“#bgimg”);

    instead works.

  25. Hi there,
    really great tutorial, really great navigation, Mary Lou.

    I want to name my photos. Does anybody has gone further with the topic of thumbnail description? A hint would be great. I have tried new classes for the pictures, but that does not work.

    Bye,
    Sarah

  26. Hi AJ, thank you! It’s free, you can use it in your personal or commercial projects. Cheers, ML