Growing Thumbnails Portfolio

Growing Thumbnails Portfolio

In this tutorial we will be making a portfolio with HTML5, jQuery and CSS3 that features an interesting growing effect.

The HTML

As usual, we start off with a blank HTML5 document, and add the needed stylesheets, markup and JavaScript includes.

<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8" />
        <title>Growing Thumbnails Portfolio with jQuery &amp; CSS3 | Tutorialzine Demo</title>

        <!-- The stylesheet -->
        <link rel="stylesheet" href="assets/css/styles.css" />

        <!-- Google Fonts -->
        <link rel="stylesheet" href="http://fonts.googleapis.com/css?family=Rochester|Bree+Serif" />

        <!--[if lt IE 9]>
          <script src="http://html5shiv.googlecode.com/svn/trunk/html5.js"></script>
        <![endif]-->
    </head>

    <body>

		<header>
			<h2>Welcome to</h2>
			<h1>Dan's Portfolio</h1>
		</header>

        <div id="main">

        	<h3>My Latest Projects</h3>

        	<a class="arrow prev">Prev</a>
        	<a class="arrow next">Next</a>

        	<ul id="carousel">
        		<li class="visible"><a href=""><img src="assets/img/sites/s1.jpg" alt="" /></a></li>
			<!--  Place additional items here -->
        	</ul>

        </div>

        <!-- JavaScript includes - jQuery and our own script.js -->
		<script src="http://code.jquery.com/jquery-1.7.2.min.js"></script>
		<script src="assets/js/script.js"></script>

    </body>
</html>

The important bit to note here is the #carousel unordered list. This element holds a collection of li items that represent your recent works.  The visible class is only added if the thumbnail is to be shown. Only three thumbnails will be visible at a time. The href attribute of the hyperlink can point to the website in question, or a larger version of the image if you plan to use a lightbox together with this example.

Growing Thumbnail Portfolio

Growing Thumbnail Portfolio

The JavaScript

All of the JavaScript/jQuery code for this example resides in assets/js/script.js. We will write a JavaScript class called Navigator that will manage the carousel for us. This will involve writing methods for listening for clicks on the arrows, partitioning the carousel into groups of 3 items and showing them.

Here is how the class will be used:

$(document).ready(function(){

	// Initialize the object on dom load
	var navigator = new Navigator({
		carousel: '#carousel',
		nextButton: '.arrow.next',
		prevButton: '.arrow.prev',
		// chunkSize:3,
		shuffle: true
	});

	navigator.init();
});

When the document is loaded, we will create an instance of the class, passing the carousel div, the arrows and an optional parameter for whether you want the list to be shuffled. There is one more parameter that can go here – chunkSize. This property determines how many thumbnails will be featured at once, the default is 3.

The first step to achieve this, is to write the layout of the class:

// A Navigator "class" responsible for navigating through the carousel.
function Navigator(config) {

	this.carousel = $(config.carousel); //the carousel element
	this.nextButton = $(config.nextButton); //the next button element
	this.prevButton = $(config.prevButton); //the previous button element
	this.chunkSize = config.chunkSize || 3; //how many items to show at a time (maximum)
	this.shuffle = config.shuffle || false; //should the list be shuffled first? Default is false.

	//private variables
	this._items = $(config.carousel + ' li'); //all the items in the carousel
	this._chunks = []; //the li elements will be split into chunks.
	this._visibleChunkIndex = 0; //identifies the index from the this._chunks array that is currently being shown

	this.init = function () {

		// This will initialize the class, bind event handlers,
		// shuffle the li items, split the #carousel list into chunks

	}

	// Method for handling arrow clicks
	this.handlePrevClick = function(e) {};
	this.handleNextClick = function(e) {};

	// show the next chunk of 3 lis
	this.showNextItems = function() {};

	// show the previous chunk of 3 lis
	this.showPrevItems = function() {};

	// These methods will determine whether to
	// show or hide the arrows (marked as private)
	this._checkForBeginning = function() {};
	this._checkForEnd = function() {};

	// A helper function for splitting the li
	// items into groups of 3
	this._splitItems = function(items, chunk) {};
}

We are using an underscore to denote which properties and methods are private. External code should not use any property that starts with an underscore.

In the fragments below you can see how each of the methods are implemented. First comes init(), which sets up the carousel by  binding event listeners and partitioning the carousel ul.

this.init = function () {

	//Shuffle the array if neccessary
	if (this.shuffle) {
		//remove visible tags
		this._items.removeClass('visible');

		//shuffle list
		this._items.sort(function() { return 0.5 - Math.random() });

		//add visible class to first "chunkSize" items
		this._items.slice(0, this.chunkSize).addClass('visible');
	}

	//split array of items into chunks
	this._chunks = this._splitItems(this._items, this.chunkSize);

	var self = this;

	//Set up the event handlers for previous and next button click
	self.nextButton.on('click', function(e) {
		self.handleNextClick(e);
	}).show();

	self.prevButton.on('click', function(e) {
		self.handlePrevClick(e);
	});

	// Showing the carousel on load
	self.carousel.addClass('active');
};

Next are the methods for handling arrow clicks.

this.handlePrevClick = function (e) {

	e.preventDefault();

	//as long as there are some items before the current visible ones, show the previous ones
	if (this._chunks[this._visibleChunkIndex - 1] !== undefined) {
		this.showPrevItems();
	}
};

this.handleNextClick = function(e) {

	e.preventDefault();

	//as long as there are some items after the current visible ones, show the next ones
	if (this._chunks[this._visibleChunkIndex + 1] !== undefined) {
		this.showNextItems();
	}
};

They call showPrevItems and showNextItems respectfully:

this.showNextItems = function() {

	//remove visible class from current visible chunk
	$(this._chunks[this._visibleChunkIndex]).removeClass('visible');

	//add visible class to the next chunk
	$(this._chunks[this._visibleChunkIndex + 1]).addClass('visible');

	//update the current visible chunk
	this._visibleChunkIndex++;

	//see if the end of the list has been reached.
	this._checkForEnd();

};

this.showPrevItems = function() {

	//remove visible class from current visible chunk
	$(this._chunks[this._visibleChunkIndex]).removeClass('visible');

	//add visible class to the previous chunk
	$(this._chunks[this._visibleChunkIndex - 1]).addClass('visible');

	//update the current visible chunk
	this._visibleChunkIndex--;

	//see if the beginning of the carousel has been reached.
	this._checkForBeginning();

};

The above methods remove or assign the visible class, which is how we control the visibility of the thumbnails. It is a good idea to hide the previous/next arrow if there are no further items to show. This is done with the checkForBeginning and checkForEnd methods.

this._checkForBeginning = function() {
	this.nextButton.show(); //the prev button was clicked, so the next button can show.

	if (this._chunks[this._visibleChunkIndex - 1] === undefined) {
		this.prevButton.hide();
	}
	else {
		this.prevButton.show();
	}
};

this._checkForEnd = function() {
	this.prevButton.show(); //the next button was clicked, so the previous button can show.

	if (this._chunks[this._visibleChunkIndex + 1] === undefined) {
		this.nextButton.hide();
	}
	else {
		this.nextButton.show();
	}
};

Lastly, here is the splitItems method, which generates the chunks. It relies on the splice JavaScript method for removing parts of the array and adding them to the splitItems array (it becomes an array of arrays):

this._splitItems = function(items, chunk) {

	var splitItems = [],
	i = 0;

	while (items.length > 0) {
		splitItems[i] = items.splice(0, chunk);
		i++;
	}

	return splitItems;

};

Congrats! You now have a working example. We are only left with styling it.

Growing CSS3 Effect

Growing CSS3 Effect

The CSS

The styling of the portfolio is defined in assets/css/styles.css. Only the more interesting parts are shown here, as the rest is omitted for brevity.

#carousel{
	margin-top:200px;
	text-align:center;
	height:60px;
	background-color:#111;
	box-shadow:0 3px 5px #111;

	/* Initially hidden */
	opacity:0;

	/* Will animate the grow effect */
	-moz-transition:0.4s opacity;
	-webkit-transition:0.4s opacity;
	transition:0.4s opacity;
}

#carousel.active{
	opacity:1;
}

/* The thumbnails, hidden by default */

#carousel li{
	display:none;
	list-style:none;
	width:150px;
	height:150px;
	margin: -82px 18px 0;
	position:relative;

	-moz-transition:0.4s all;
	-webkit-transition:0.4s all;
	transition:0.4s all;
}

/* This class will show the respective thumbnail */

#carousel li.visible{
	display:inline-block;
}

#carousel li a img{
	border:none;
}

#carousel li img{
	display:block;
	width:auto;
	height:auto;
	max-width:100%;
	max-height:100%;
	position:relative;
	z-index:10;
}

/* Creating the cradle below the thumbnails.
	Uses % so that it grows with the image. */

#carousel li:after{
	content:'';
	background:url('../img/cradle.png') no-repeat top center;
	background-size:contain;
	bottom: 4%;
    content: "";
    height: 50px;
    left: -6.5%;
    position: absolute;
    right: -6.5%;
    width: auto;
    z-index: 1;
}

/* Enlarging the thumbnail */

#carousel li:hover{
	height: 197px;
    margin-top: -152px;
    width: 222px;
}

With this our Growing Thumbnails Portfolio is complete!

It’s a wrap!

You can easily customize today’s example by incorporating a lightbox script, increasing the number of thumbnails shown at once, or even by turning it into a gallery. If you do something interesting be sure to share it in the comment section below!

Join our newsletter and get our PSDs!20,109 people learn about HTML5, JS and more. Join them!

by Martin Angelov

Martin is a web developer with an eye for design from Bulgaria. He founded Tutorialzine in 2009 and it still is his favorite side project.

14 Comments

  1. FINESTGOL says:

    Good Thumbnails Portfolio.

  2. Linus says:

    Great stuff man!

  3. Looking very good, thanks for sharing!

  4. Imran says:

    I like this thumbnail portfolio but it would be more good if when we click on next the thumbnail should move with animation not just bump to next 3 pics.
    Otherwise Its very good, I like it.

    1. Tilo says:

      Imran, the beauty of this code is that it's nice and organized. To add in your desired effect, you just have to edit the showNextItems() and showPrevItems() method.

      In each of these, you would add a CSS classname to the <li> elements, and you can specify the transition inside the CSS.

  5. Nice css3 effect. Thank you

  6. humbu says:

    Thanks you for giving us free tutorials anyway your my hero i wish if i can think and code like you nice tutorial

  7. Rawaf says:

    Good thumbnails protfolio and nice CSS3 effect
    thank you

  8. Sven says:

    Nice, but the mousover could be a bit softer.

  9. Really nice portfolio effect, thanks for sharing! :)

  10. Time says:

    Great portfolio! Excellent!

  11. jerald says:

    excellent

  12. Nice and clever use of CSS3

  13. Robert says:

    I did think of this kind of animation earlier, but just didn't get a chance to implement it.The key part where your idea differs from mine is that I wanted to do this in pure CSS and make it cross-browser compliant.If I do get some time, I will try to implement my solution & will leave you the demo URL so that you can check it out & leave me your feedback.

Add Comment

Add a Reply

HTML is escaped automatically. Surround code blocks with <pre></pre> for readability.
Perks:   **bold**   __italics__   [some text](http://example.com) for links