Tutorials

Create A Simple Responsive Portfolio Page with Filtering and Hover Effect (Updated)

Written by Kevin Liew on 29 Apr 2016
398,153 Views • Shares
133 comments

Previously, I was showing how to create portfolio page with filtering and also hover effect for each of your project item. We achieved that effect with CSS3 and jQuery filter & sort plugin called MixItUp.

The response was pretty good, it has been in our popular post list for quite sometimes too. I guess it's due to the fact that filtering UI is quite a popular thing to implement. So, I was looking at the comment, I think I need to do an update and fix some of the issues.

Alright, this time it's not just fixing the issues but with some enhancements as well. Here's the updates:

  • MixItUp is now version 2.1.11, the one we used is way outdated. The good news is, the new one can load your desired filter on first run, not just showing all of it.
  • Easing plugin is removed and replaced with CSS3 transition instead. We can achieve the same thing with smaller file size and less JS. So, why not?
  • There're a couple of comments mentioned there's a bug that causing the whole thing moved 3-4px to the left. It's actually not an issue, because when you show ALL, the content became longer. Therefore, in IE you have a scrollbar displayed on the right which causing the undesired sudden movement that moves everything to the left. I didn't see this because I'm on Mac and scrollbar hover above the content instead of taking up the website viewport space.

I'm trying to keep everything the same so you can update it easily. This script will work pretty well with our previously published tutorial - display images with shape masking and nifty zoom effect.

Alright, lets get it started. First of all this is the screenshot of what we are about to build:

Based on the layout there are two main UI elements we need to build - Tab navigation for filtering and a grid of portfolio with hover effect. After that we will hook it up with MixItOut and our custom hover script.

HTML

First of all, we have the HTML markup for Tab navigation. It's a UL list with data filter. data-filter is included because MixItUp needs it for its filtering. It's updated to conform to the new MixItUp formatting. Classes are specified in data-filter to be consistent with jQuery filter()

<ul id="filters" class="clearfix">
<li><span class="filter active" data-filter=".app, .card, .icon, .logo, .web">All</span></li>
<li><span class="filter" data-filter=".app">App</span></li>
<li><span class="filter" data-filter=".card">Card</span></li>
<li><span class="filter" data-filter=".icon">Icon</span></li>
<li><span class="filter" data-filter=".logo">Logo</span></li>
<li><span class="filter" data-filter=".web">Web</span></li>
</ul>

Under the Tab navigation, we have portfolio list. We need to assign each portfolio a category in data-cat attribute. By matching data-filter with data-cat, this is how MixItUp filters portfolios.

Other than that, we added label and hide it by default. We will show it on mouse hover with CSS3.

<div id="portfoliolist">
  <div class="portfolio logo" data-cat="logo">
    <div class="portfolio-wrapper">
      <img src="img/portfolios/logo/5.jpg" alt="" />
      <div class="label">
        <div class="label-text">
          <a class="text-title">Bird Document</a> 
          <span class="text-category">Logo</span>
        </div>
        <div class="label-bg"> </div>
      </div>
    </div>
  </div>
.........
</div>

CSS

We divided CSS into two parts - general styling for UI elements and responsive.

html {
  overflow-y: scroll;
}

.container { 
	position: relative; 
	width: 960px; 
	margin: 0 auto; 
	-webkit-transition: all 1s ease;
  -moz-transition: all 1s ease;
  -o-transition: all 1s ease;
  transition: all 1s ease;	
}
 
#filters {
	margin:1%;
	padding:0;
	list-style:none;
}

	#filters li {
		float:left;
	}
	
	#filters li span {
		display: block;
		padding:5px 20px;		
		text-decoration:none;
		color:#666;
		cursor: pointer;
	}
	
	#filters li span.active {
		background: #e95a44;
		color:#fff;
	}
 

 
#portfoliolist .portfolio {
	-webkit-box-sizing: border-box;
	-moz-box-sizing: border-box;
	-o-box-sizing: border-box;
	width:23%;
	margin:1%;
	display:none;
	float:left;
	overflow:hidden;
}

	.portfolio-wrapper {
		overflow:hidden;
		position: relative !important;
		background: #666;
		cursor:pointer;
	}

	.portfolio img {
		max-width:100%;
		position: relative;
		top:0;
    -webkit-transition: all 600ms cubic-bezier(0.645, 0.045, 0.355, 1);
    transition:         all 600ms cubic-bezier(0.645, 0.045, 0.355, 1);		
	}
	
	.portfolio .label {
		position: absolute;
		width: 100%;
		height:40px;
		bottom:-40px;
    -webkit-transition: all 300ms cubic-bezier(0.645, 0.045, 0.355, 1);
    transition:         all 300ms cubic-bezier(0.645, 0.045, 0.355, 1);
	}

		.portfolio .label-bg {
			background: #e95a44;
			width: 100%;
			height:100%;
			position: absolute;
			top:0;
			left:0;
		}
	
		.portfolio .label-text {
			color:#fff;
			position: relative;
			z-index:500;
			padding:5px 8px;
		}
			
			.portfolio .text-category {
				display:block;
				font-size:9px;
			}
	
	.portfolio:hover .label {
    bottom:0;
  }
	.portfolio:hover img {
    top:-30px;
  }  

A simple responsive layout to make sure the grid display properly in different window dimension. Removed this bit if you have your own responsive grid system.

/* #Tablet (Portrait) */
@media only screen and (min-width: 768px) and (max-width: 959px) {
	.container {
		width: 768px; 
	}
}

/*  #Mobile (Portrait) - Note: Design for a width of 320px */
@media only screen and (max-width: 767px) {
	.container { 
		width: 95%; 
	}
	
	#portfoliolist .portfolio {
		width:48%;
		margin:1%;
	}		
}

/* #Mobile (Landscape) - Note: Design for a width of 480px */
@media only screen and (min-width: 480px) and (max-width: 767px) {
	.container {
		width: 70%;
	}
}

Javascript

Lastly, we have the Javascript. You can change its setting by visiting its documentation. They have updated it with a lot of explanation and samples. That's a pretty good job. You can check out the animation configuration to see what else effect can you achieve too.

$(function () {
		
	var filterList = {
	
		init: function () {
		
			// MixItUp plugin
			// http://mixitup.io
			$('#portfoliolist').mixItUp({
				selectors: {
  			  target: '.portfolio',
  			  filter: '.filter'	
  		  },
  		  load: {
    		  filter: '.app' // show app tab on first load
    		}     
			});								
		
		}

	};
	
	// Run the show!
	filterList.init();
	
});		

Conclusion

Nowadays, designers tend to cut down the clutters and keep everything simple. With this tutorial, we created a simple filtering portfolio page with hover effect. Sometimes we don't have to reinvent the wheel. With all sort of plugins available today, we can easily produce the effect we want by combining different javascript plugins.

Hopefully this update will solve a lot of questions you have. Drop a comment if you have any questions. Enjoy!

Demo Download
Join the discussion

Comments will be moderated and rel="nofollow" will be added to all links. You can wrap your coding with [code][/code] to make use of built-in syntax highlighter.

133 comments
Henry 4 years ago
May I develop again and distibute more?

Thank you
Reply
Asif Khan 4 years ago
But how can I implement this dynamically in wordpress ?
Reply
th3lonius 4 years ago
I really don't understand why this isn't working for me. I am implementing with Wordpress and all of my categories for classes and data-filters are queried correctly. Just to be sure, I have used your code to the letter, meaning I've used your exact HTML and CSS structure with your class names and the same exact initializing function with jQuery. I just don't get it.

My filter list displays of course, but the portfolio list does not. Please help.
Reply
fabian6r 4 years ago
add this bro! :

<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>



;)
Reply
Umberto 4 years ago
Very good job!
Thank you! :)
Reply
fil 4 years ago
hi, after several try, the runs. i am a beginner with coding and adjust some css lines e.g. width, but it overrides bootstrap 3 css files and not display the text title. what i am doing wrong?
Reply
Paul 4 years ago
Great demo! Works great for me thanks. I'm just trying to do one more thing:

I would like it to filter into one specific category on page load. in this demo then you would go on the page and 'card' for example would be all that is shown.

I've tried some similar code used in this thead.. http://codepen.io/patrickkunka/pen/sjlBG

I'm not sure how to work anything into the code in this demo..

$(function () {

var filterList = {

init: function () {

// MixItUp plugin
// http://codepen.io/patrickkunka/pen/sjlBG
$('#portfoliolist').mixitup({
targetSelector: '.portfolio',
filterSelector: '.filter',
effects: ['fade'],
easing: 'snap',
// call the hover effect
onMixEnd: filterList.hoverEffect()
});

},

Can anyone help?
Reply
G in Nashville 4 years ago
I'd like to know how to do this as well.
Reply
pj 4 years ago
Here's what I've done, this script is located just below the body tag.


<script type="text/javascript">

$("window").ready(function() {
$("#homepage").trigger('click');
});
</script>

<ul id="filters" class="clearfix">
<li><span class="filter active avail" id="homepage" data-filter="home">Home</span></li>
<li><span class="filter" data-filter="corp">Corporate</span></li>
<li><span class="filter" data-filter="wedd">Weddings</span></li>
<li><span class="filter" data-filter="awards">Awards</span></a></li>
<li><span class="filter avail" data-filter="avail">Availability</span></a></li>
<li><span class="filter" data-filter="faq">FAQ</span></li>
</ul>


it works okay on FF and Safari, but not on Chrome, I guess the pop-up blocker differentiates between a triggered click and a user click. Also, it doesn't work at all on my Samsung S4, which just may be a javascript issue. If anyone has any other advice please let me know. My email address is writepj@yahoo.com I wrote Kevin tonight and he sent me these guides, please let me know if you can make sense of it as I could not. Thanks.

Kevin's advice:

You can use hashtag. eg, from the tutorial. we have data filter - app, card, icon, logo...

so, if user access the page via this url http://urdomain.com/portfolio#app, you can do this:

1. check for hashtag
2. grab the hashtag (you might need to remove "#" symbol from it)
3. then find the .filter with the correct filter (hashtag == data-filter), and trigger a click on it, it should automatically filter it.

Reply
Mudit Chauhan 4 years ago
Hi Kevin,

Good work!
but can you tell me how can I add lightbox effect after click on any portfolio image?
Reply
Artur Haddad 4 years ago
For those with problems with image/thumbs loading simply remove the line:
"//hide its label by default"
It's causing an error in css
Reply
Marc Stampfli 4 years ago
Hello, i'm trying to use this for a site i'm building and i got it working almost 100%.

The only way it shows the portfolio items is on the "ALL" filter on intial page load, when i try to click the other filters they all disappear and when i try to click back to view all of them, they still stay hidden.

Any idea on this?
Reply
Marc Stampfli 4 years ago
I have figured out my problem. Works fine now.
Reply
Beladel Ilyes Abdelrazak 4 years ago
Great tutorial, but you should mention that the plugin is not for commercial use until purchase a developer license.
Reply
Chintan 4 years ago
How can we add multiple data filters for a single product. In other words, i want to add one product to web and also in logo. How can that be done??
Reply
Astrit 4 years ago
Ever thought about turning this script into search engine friendly? If javascript is disabled all the content goes hidden, it would be good if the content is visible if javascript is disabled.
Reply
Imran 4 years ago
Thanks for your wonderful tutorial. But I want to dynamic it in wordpress. So, Can I know that how to dynamic mixitup in wordpress. I have searched Google. But I am not satisfied. Can you please make a tutorial for me or everyone also.

Thanks Imran
Reply