Learn and share. The simplest harmony.


Filter Image View Using jQuery

Posted on May 13, 2010 and got 83 shouts so far

Tobias Ahlin is a great designer from Sweden, I admire his work and his way showcasing his portfolio. It comes up with the list of all his works and the anchor for filtering work type above them, we can choose one of the filter and it’s automatically hiding and showing portfolio item using horizontal slide effect. Now, in my view, I am going to explain how they beautifully works.

I’ve put together the request from webstuffshare visitor, the updates are Paging, Lightbox integration, Text explanation under the gallery. You can download the update in here http://www.webstuffshare.com/download/FilterImages2.zip

The Technique
As you can see on the demo page, the image items are showing and hiding with horizontal slide effect based on user choice. Horizontal slide effect produced by manipulating item’s width, when hiding the item we will change the item width into 0 pixel, and when showing the item we will return its default width.

To make the item’s width transformation smooth we will also change its opacity, for hiding the item set the opacity from 100% to 0% and vice versa for showing them. We can show and hide the item but we won’t see the slide effect transition, so we must use built-in jQuery function, animate().


Setup The Item’s View
We’ll create two separated section, first the navigation and the last is the items list. The navigation will contains anchor links which will navigate the items visibility, while items list will contains image item which will be show and hide.

Now, create navigation and items list like following script :

As you mention above, each navigation and item has rel attribute that represent each category. The purpose is when user choosing one of the navigation, the items that will be displayed only an item which has same rel attribute with the navigation, the others will be hidden.

We will styling the navigation first, set the list display with inline-block so the unordered list will be displayed horizontally. If the user select one of the navigation, we will add “selected” class name to them. “selected” style are having green background with box-shadow and border radisu, so the selected navigation will have different style with the siblings.

ul.menu {
	margin-left: .5em;
	margin-bottom: 1em;

ul.menu li {
	list-style-type: none;
	display: inline-block;
	font-weight: bold;
	text-shadow: 1px 1px 0px #f3f5da;
	padding: 2px 15px;

	.selected {
		-webkit-border-radius: 15px;
		-moz-border-radius: 5px;
		border-radius: 5px;
		background: #acac75;
		-webkit-box-shadow: 1px 1px 0px #8c8c5d;

	.selected a, .selected a:visited {
		text-shadow: 1px 1px 0px #8c8c60;
		color: #fff;


Now styling the image items, set each item display with block, list style type with none, float with left and margin with 0.5 em. Each image inside the list will have 5pixels white border thickness, border radius 5 pixels and also box shadow.

ul.item li {
	list-style-type: none;
	display: block;
	float: left;
	margin: .5em;

	ul.item li img {
		border: 5px solid #fff;
		-webkit-border-radius: 5px;
		-moz-border-radius: 5px;
		border-radius: 5px;
		-webkit-box-shadow: 0px 0px 5px #ac987e;
		-moz-box-shadow: 0px 0px 5px #ac987e;
		box-shadow: 0px 0px 5px #ac987e;


Slide Effect With animate()
The slide effect will fire up when user click the navigation, so we will add click event to them. After that, remove “selected” class name from all navigation and add it to selected navigation. This will make selected navigation will have different style with its siblings.

$('.menu li a').click(function() {
	$('.menu li').removeClass('selected');

Next, get its rel attribute value and check it. If the value is “all” (which mean showing all image item) we will display all image item and if the value is other we will search any image item that has same rel attribute value and display it then hide the others.

thisItem 	= $(this).attr('rel');

if(thisItem != "all") {

	$('.item li[rel='+thisItem+']').stop()
	.animate({'width' : '110px',
				 'opacity' : 1,
				 'marginRight' : '.5em',
				 'marginLeft' : '.5em'

	$('.item li[rel!='+thisItem+']').stop()
	.animate({'width' : 0,
				 'opacity' : 0,
				 'marginRight' : 0,
				 'marginLeft' : 0
} else {

	$('.item li').stop()
	.animate({'opacity' : 1,
			 'width' : '110px',
			 'marginRight' : '.5em',
			 'marginLeft' : '.5em'

As you can see above, for displaying the item we search all item which having same rel attribute value with the selected navigation. Then we start the animation which will animate the item width to the image’s width, set its opacity to 100% and set each margin left and right to 0.5em. To prevent animation queue, we use stop() function before animate() function.


For hiding the sibling we use the same technique as above except the animation properties’s value, set each animation properties’s value to 0.

At this point our item will be show and hide using slide effect, triggered by the navigation. The last thing we will do is to make the image items smoother by adjusting its opacity. Set each image opacity to 50% using animation and hover toggle event, if the user hovering it, animate its opacity to 100% and revert it value to 50% when user hovering out.

$('.item li img').animate({'opacity' : 0.5}).hover(function() {
	$(this).animate({'opacity' : 1});
}, function() {
	$(this).animate({'opacity' : 0.5});

Ok, that’s it. Thanks for reading and hope this post useful :)


This Post Tags :

Bookmark Post :

Pin It
  • Oh very nice! I like the effect and I think I’ll use something like this for the restyling of my own portfolio.
    Thanks for sharing!

  • Great effect! Reminds me a little of Quicksand (http://razorjack.net/quicksand/) but your effect has its own unique charm! I suggest that you turn it into a proper plugin, stick the code on Google Code (or GitHub) and add it to the jQuery Plugin repository at http://plugins.jquery.com/

  • That’s a really useful filter. I wonder whether it’s possible to add multiple keyword-tags to the items rel attribute? Like this:
    rel=”jquery css psd”

  • Great wee tutorial, and exactly what i was looking for as part of my portfolio.


  • @All thanks for your comments!
    Credits for Tobias Ahlin for his great idea!

    @Marcus Tucker
    That’s a great idea, but I think I need to talk to the author of the idea first :)

    Certainly you can do that, for finding the items you can use attribute contains word selector : [rel~=value]

  • Great tutorial…Thanks. I’m trying to get into using more jQuery it does some really cool things..

  • Thanks for sharing! Very nice effect achieved with such minimal coding.

  • thanks mate Tobias Ahlin ;)
    matur nuwun kang H.Sagita…
    hmmm…any Mrs Sarah William theres…;)) ;) :”> :p

    • It turns out that the long code, I found this boss …
      <script type=’text/javascript’>
      $(document).ready(function() {
      $(“#B2nImg img”).fadeTo(“slow”,0.5);
      $(“#B2nImg img”).hover(function() {
      $(this).fadeTo(“slow”,1);},function() {

      <a href=’http://www.blah-bleh-bloh.com/’ id=’B2nImg’ title=”><img alt=” border=’0′ src=’http://blah-bleh-bloh.jpg’></a>

  • The javascript code looks not very complicated, but it does a great job. The effect is very cool. Thank you very much for this tutorial.

  • Thank you for this tutorial.

  • thank you for the code! i can not get fancybox.net to work on my images.

    my filters are:

    using fancybox:
    - filter ALL, select and image ….works-launches fancybox

    - filter ONE , select and image ….DOES NOT launch fancybox

    - go back and filter again on ALL, select and image ….DOES NOT launch fancybox

    any help greatly appreciated

    • Hi,

      Can you tell me how you got it to work with Fancy Box at all? Did you rewrite the classes? Thanks!

  • @deb :
    Hi, would you please put your online example so I can also try an debug your code.

  • Awesome tutorial!!
    I had been working on something similar but for some reason it refused to work in IE but glad to see the is cross-browser compatible!

    One question though… The animations dont seemt o be working in Safari?? Is it just my Safari or is there a fix I can use for this??

  • @kris
    Thanks kris! I created them while using Safari and they’re works fine, would you please put the problem detail?

  • Great work! Exactly what I have been looking for. I know you touched on this above, but I’m confused on how to implement it in the script.

    I have several items that will fall under multiple categories. One item may be included under css and jquery.
    “use attribute contains word selector : [rel~=value]“. Where does this go and what changes in the script. I tried swapping [rel!='+thisItem+'] with [rel~='+thisItem+'] but it didn’t work.

  • @Jason If you want to select any div element that having ‘rel’ attribute with value ‘blah’ you can do this : $(‘div[rel~=blah]‘) or select any div element that having ‘rel’ attribute without value .

    In this case you can’t swap them, if you have multiple categories you can put category name on each list in rel attribute.

  • Very cool and useful tutorial! I have one question though. How can we make it work with multiple rel values? It works with rel=”abc” but it doesn’t work with rel=”abc def”.
    This question have been aksed here already but still I can’t figure it out.
    I’ve got my portfolio items under multiple categories and I’d like it to work with multiple rel=”" attributes. Is this possible?

  • Great code! Can you please explain a little more about having multiple categories. Like Jason, I cant seem to get the ‘use attribute contains word selector’ to work properly.

  • This and Tobias’s script have a bug : the last item not disappear after filtering. If you roll over last item, the link is active.
    I’m searching for.. if i found the solution, i’ll post here.

  • This solution seems to work :

    $(‘.item li[rel!='+thisItem+']‘).stop().animate({‘width’ : 0, ‘opacity’ : 0,’marginRight’ : 0},function(){$(‘.item li[rel!='+thisItem+']‘).css(“display”,”none”);});

    I’m wating for a better solution..

  • $('.item li[rel!='+thisItem+']').stop().animate({'width' : 0, 'opacity' : 0,'marginRight' : 0},function(){
    $('.item li[rel!='+thisItem+']').css("display","none");});

    You have to hide (display:none) the non-selected item after the transition.
    It seems to work.

  • I’va found a solution but i can’t post code here.
    You have to hide (display:none) the non-selected item after the transition.
    It seems to work.

  • rel~=’+thisItem+’]’ doesn’t seem to be working. :(

  • Hi There, great script by the way.

    Unfortunately the HTML5 specification will not allow ‘rel’ on a element.

    do you know a way round this at all?

    Many thanks

    • I’d like to know this as well. My HTML Validator says there is no attribute “rel” on a element. How do we avoid this problem?

  • Hi there,

    Excellent code! Just one question…
    What would you do if one tutorial had 2 or more topics (let’s say css and psd) and you wanted to show it when clicking on any of the 2?


  • Looks nice

  • I really love your design aesthetic. This tutorial is great. I am trying to add to it but am having problems. I want to add prettyPhoto lightbox so that when you click on the image it expands and plays. To do that do I need to combine the two classes (the one from you and the one from prettyPhoto) into one class to make it work? or can I use these two classes together without having to rewrite them into one class? New to jQuery. see: http://www.no-margin-for-errors.com/projects/prettyphoto-jquery-lightbox-clone/


    • You can put this on your head tag:
      <link rel=”stylesheet” type=”text/css” media=”screen, projection” href=”http://www.no-margin-for-errors.com/wp-content/themes/NMFE/css/prettyPhoto.css” />
      <script src=”http://www.no-margin-for-errors.com/wp-content/themes/NMFE/js/jquery.prettyPhoto.js” type=”text/javascript” charset=”utf-8″></script>

      After this line :
      $(document).ready(function() {
      Put this code :
      $(“a[rel^='prettyPhoto']“).prettyPhoto({theme: ‘facebook’,slideshow:5000, autoplay_slideshow:true});

      On the list item :
      <li rel=”jquery”><a rel=”prettyPhoto” href=”put your big image’s link“><img src=”images/button.jpg” /></a></li>

      • Thanks, I got it working. The other bug is this: When I filter by image the first image in the series doesn’t open with one click (I have to click twice on it). The rest of the images in the series open on one click (while filtering by category). If I filter by All and click the first image in a category while in ALL view, it opens on one click) and then when I filter by category the first image (same image I clicked in ALL view) in the series in that category will open on one click but first I had to open it in ALL view. ALL view works fine, this bug just shows up when I am in the filter by category/image and it’s only the first image in each category that takes two clicks to open.

  • I would like to know how to default the images to ’1″ opacity and then when hovering over an image, the other images will fall to opacity ‘.5′. Is this possible?

    • You can use this code :

      $(‘.item li img’).hover(function() {
      $(‘.item li img’).not(this).animate({‘opacity’ : .5});
      }, function() {
      $(‘.item li img’).animate({‘opacity’ : 1});

      to replace this code :

      $(‘.item li img’).hover(function() {
      $(‘.item li img’).not(this).animate({‘opacity’ : .5});
      }, function() {
      $(‘.item li img’).animate({‘opacity’ : 1});

  • Excellent solution but can you suggest how to implement it to use with Joomla! and prettyPhoto?

    Thanks for assist!

  • I found out one bug in your code, if you gallery is at the bottom of the page and your click any link for filtering….

    It goes to the top of the page….i mean that if automatically scrolls upwards to the top of the page…….is there any solution to the problem…….

    • use href=”id.of.parent.div” for the a tag for the time being, so that on clicking it goes to that div, instead of going to the top.

      • Ah, better solution..

        prevent the whole action with a [b]return false[/b], like
        $('.menu li a').click(function() {

        return false;

        • SAIKAT

          where exactly do i have to put this code in the , i hope you understand the problem if not here is what it is

          There is bug in the demo http://www.webstuffshare.com/download/FilterImages2.zip
          if you click on the Pagination ’2′ in ‘All Tutorial’ page and then select the next filter ‘Jquery tutorial’ you will see nothing basically what happens the page is scrolled in all the filter pages .so inorder to see the contents in all pages you have to go to ‘All Tutorial’ page and then click pagination ’1′… I hope you understand the bug …

          will your above code solve this issue?

  • Can you add lightbox?

  • Question:

    Is there a way to view the thumbnails largely using a gallery of some sort integrated into this plugin?

    The way it’s set up is when you click on the thumbnail, it opens a new web page (because of the a href attribute) but it would be nice to click on the thumbnail and open up the full size image onto the website.

    Your file was very clean and worked perfectly integrated into my site, it would be even MORE perfect if I could figure out a way to do this….


    • @analia & danielle
      I’ve put together the request from webstuffshare visitor including your request. The updates are :

      1. Paging.
      2. Lightbox integration.
      3. Text explanation under the gallery.

      You can download the update in here http://www.webstuffshare.com/download/FilterImages2.zip

      • Hi
        I tied using your Filter Images with Light box integration.

        But each time I chick on “2″ and then change category the images do not appear

        It only works if “1″ is selected before changing category

        Is there a fix for that


        • It’s because their marginTop has been changed, you can add this line :

          $('.menu li').removeClass('selected');

          after this line :

          $('.menu li a').click(function() {

  • Awesome effect, i’ve been trying to make it works on WordPress but something i’m missing, i guess, i’m using “nicenames” to call the categories because i use the qTranslate plugin and i don’t want get messing with the langs.

    I can’t get the “category” in rel attribute. I’m using this for call the nicenames (inside the loop):


    Do i need to modify the jQuery? Thank you in advance.

  • Sorry, this is the code:


    • I don’t think you need to change the jQuery, you just need to get the category, maybe this thread useful http://wordpress.org/support/topic/category-gtcategory_nicename

      • hi, i’m having the same issue, i can’t get the category on the rel on the loop, did anyone solved this already? that thread didn’t help me :\

    • Hi Huroma
      Can you tell us if you have solved the problem with wordpress?
      and how?
      I’m trying but I have some problems.

  • You can change the buttons to select
    images by “selectbox”?

    the buttons are “selectbox”


  • Awesome work! I used the latest version and moved around some things for my portfolio here: http://www.drselkirk.com/portfolio-work/#AllWork


  • First off the code is great and does exactly what I was hoping that it would.

    One question though:

    How can i set it to automatically load with a specific filter applied. In other words… remove “show all” completely.

    I am essentially trying to use the links as navigation between groups of photos but I never want all of the photos to be shown at once.

    I am sure that this is an easy fix but my javascript knowledge is very minimal. Thanks in advance.

    • well… a rather unelegant way of solving this was to hard code the width, opacity, and margins to 0 on the photos that I didnt want to display on load.

      It is working right now but is there a purely scripted way of doing this without hardcoding css values?

      • Considering ‘jquery’ being a first load, then add this code :

        $('.item li[rel=jquery]').stop().animate({
        'width' : '110px','opacity' : 1,
        'marginRight' : '.5em',
        'marginLeft' : '.5em'}).addClass('show');
        $('.item li[rel!=jquery]').stop().animate({
        'width' : 0,'opacity' : 0,
        'marginRight' : 0, 
        'marginLeft' : 0}).removeClass('show');
  • hi, could you explain what we need to do to get multiple categories working? I cant figure out how the solution to use divs above works. Help please :) Thanks!

    • no worries, i figured it out.. solution:


      $(‘.filteritem li[rel='+thisItem+']‘).stop()
      $(‘.filteritem li[rel~='+thisItem+']‘).stop()


      $(‘.filteritem li[rel!='+thisItem+']‘).stop()
      $(‘.filteritem li:not([rel~='+thisItem+'])’).stop()

      Thanks for this awesome script!

      • This saved my life, thanks dude!

        • Ditto! Thanks :D

  • Hello! It looks absolutely amazing, thanks! And I find it easy enough.

    But I run in to some problems and as I have no whats so ever knowledge of jquery or javascript I could use a hand.

    Problem 1:
    Every time i press any of the filer-buttons I get scrolled pack up to the top. I’m building a single-page-website so I need it to stay where the gallery is. Any tips?

    Problem 2:

    I am using a script for making the page smooth scroll. This one:
    It’s simple and works good, but it seems to be interfering with the filter-gallery code.
    Is there a way to make them both just get along? Or even better make out with each other?

    Thank you!

    • I’ve fix problem number one, jut put return false;

      It’s look like

      $menu.click(function() {
      thisItem = jQuery(this).attr(‘rel’);
      if(thisItem != “all”) {
      jQuery(‘.item li[rel~='+thisItem+']‘).stop()
      .animate({‘width’ : ’110px’,
      ‘opacity’ : 1,
      ‘marginRight’ : ‘.5em’,
      ‘marginLeft’ : ‘.5em’

      jQuery(‘.item li:not[rel!='+thisItem+']‘).stop()
      .animate({‘width’ : 0,
      ‘opacity’ : 0,
      ‘marginRight’ : 0,
      ‘marginLeft’ : 0

      } else {
      jQuery(‘.item li’).stop()
      .animate({‘opacity’ : 1,
      ‘width’ : ’110px’,
      ‘marginRight’ : ‘.5em’,
      ‘marginLeft’ : ‘.5em’
      } return false;

    • Hello! I have the same problem: “Every time i press any of the filer-buttons I get scrolled pack up to the top. I’m building a single-page-website so I need it to stay where the gallery is.” Did you manage to figure it out perhaps? I do not have this problem when testing the site in chrome, but there is a problem in mozilla…

      Any tips welcome!

      Thank you

  • Don’t confused about $menu and $menu, i put

    var $menu = jQuery(‘.menu-portfolio li a’),
    $menus = jQuery(‘.menu-portfolio li’);


  • Is there some way to make the filter work vertically, rather than horizontally?

  • Hello! I am a newbie so all the advice is welcome :-) Thank you for the code! Though, I have a big problem:

    I am trying to build my portfolio with HTML5 and in chrome the animation works, in mozilla does not work. Everytime I select something form the menu it takes me back to the first page ( I am building a one page horizontally scroll website)

    Thank you!

    • Lou, would you mind to put your code here or give me an example link to the page you’re building, so I can try to figure it out.

    • You get scrolled back to the top of the page because the anchors for the filters all point to a href="#".

      You can create an anchor with a unique id (ie. “galleryTop”) at the top of your gallery (wherever you have it placed on your page) and change the filters links to point to it a href="#galleryTop"

      Or, you can take out the href="#" altogether and the filters will still work with the javascript. The only catch here is that it won’t appear visually as a link to the user (ie. the Cursor doesn’t change because it no longer thinks the anchor is a link, it just recognizes it as text). This can be easily fixed by adding CSS style to the div containing the filters – cursor: pointer;.

      Good luck!

  • Hiii… It looks absolutely amazing, thanks! And I find it easy enough. Thank you for sharing.

  • very hopeful scrcipt thx

  • Thanks for the great script! Very helpful indeed.

    I notice alot of people are getting hung up on the fact that when you click the filters in the gallery it takes you to the top of the page. This is simply because the links the filters are wrapped in all point to a href="#". href=”#” is just a placeholder, which points to an id (attributed with the “#” pound symbol) that doesn’t exist, so it just takes you back to the top of the html document. You can do a couple of things to resolve this easily:

    1. Add an anchor (with nothing inside of it, so it won’t take up any space on the page) to your page at the top of your gallery so it will point users there when they click the filters. ie. create the anchor with the ‘name’ or ‘id’ attribute a name="myGalleryTop"></a (hint, Name and ID must be the same if you use both, but both are not required) and then have all the links which wrap the filters point to a href="#myGalleryTop"

    2. Remove the href attribute from the anchors wrapping the filters. When clicked, they will still filter your gallery by running the javascript attached, however they won’t take you anywhere within your html document. The caveat here is that browsers will no longer read the anchors as links, just plain text, so it won’t show a “pointer cursor” when a user mouses over it like a normal text link. To fix this, just use CSS to style the anchors wrapping the filters. ie. #myGalleryTop { cursor: pointer; }

    There’s one other issue I noticed which seems common in this forum, and I also ran into myself – It can be a little troublesome clicking on the items in the gallery once they’ve been filtered. The first gallery item is hard to click on and sometimes you can still click links to gallery items which should not appear as a part of the filter. The reason for this is because the javascript is setup to make the filtered gallery results hidden (using the 0 opacity trick), but still displayed and taking up space. This can cause errors when trying to click the correct items in the gallery after filtering the results. There’s a simple fix for this as well, you just need to change the javascript so that the items which are filtered out change their opacity value to ‘hide’ instead of 0.

    $('.item li[rel!='+thisItem+']').stop()
    .animate({'width' : 0,
    'opacity' : 0,

    $('.item li[rel!='+thisItem+']').stop()
    .animate({'width' : 0,
    'opacity' : 'hide',

    and you shouldn’t have any more issues clicking your gallery items. Good luck all and thanks again to Hidayat for sharing!

    • @Shane Anderson – Thanks so much! Really nice fix to a very irritating problem

      Great script, thanks :D

  • Thanks for the great code! It is really wonderful!

    BTW, I am having one small problem with your code. With the paging put in, after I jump to another page and then choose another category, it seems like the filter is only limited to the last shown items on the page.

    Is there any way to reset items when the category is selected?

    Thanks in advance!

    - Kc

  • Fantastic! Great tutorial, and great source!

  • thanks for sharing this script, very useful.

  • Great script… Many thanks.

    Is there any way to implement a history function, pergapst to the href … so that if your images link to separate pages you could go back to the previous page and the filter still be filtered down to what you were last looking at?

    Just implement the plugins as usually and then modify the gallery’s code like this:

    jQuery(document).ready(function($) {
    $(‘.menu li a’).click(function() {

    It works, for me.

  • I implemented a different fix for the issue when you have lots of images and you seem to click through to the ones with opacity 0. You can also hover in-between images and see how the mouse picks up the images “hidden”.

    So i created a filtered class with display:hidden;

    Then, at the begining of the click function, i added this line

    $(‘.item li’).removeClass(‘filtered’);

    to remove the class from all the items

    and after the animation finished i added the class to those with opacity 0

    $(‘.item li[rel!='+thisItem+']‘).stop() .animate({‘width’ : 0, ‘opacity’ : 0, ‘marginRight’ : 0, ‘marginLeft’ : 0, }, function(){$(‘.item li[rel!='+thisItem+']‘).addClass(‘filtered’);});

    Works very well.

    • Hello,

      Where we must put the second code
      “$(‘.item li[rel!='+thisItem+']‘).stop() .animate({‘width’ : 0, ‘opacity’ : 0, ‘marginRight’ : 0, ‘marginLeft’ : 0, }, function(){$(‘.item li[rel!='+thisItem+']‘).addClass(‘filtered’);});”



  • Ive also implemented colorbox by adding


    at the end of the if(thisItem != “all”) statement.



    at the end of the else statement


    Outside the click function.

    Need to add rels group into the anchor of the images and your are done!

  • Hello,
    Really great script ;)
    I use it in my portfolio and it works perfectly. I added a ShadowBox… so cool ;)

    Thanks so much for your work

    I would know if it’s possible to get the parameter “rel” from an other page ?

    I try to explain (with my rotten english, sorry)
    I’ve 2 pages, Portfolio (where I use your script) & Clients (with “wall of logo” ) and I would like when I click on one logo in Client page, to be redirected to the portfolio page with only the references of the client “clicked” ???

    I try some solutions to get the “rel” but without succes… so if you have a solution or an idea… let me know

    So, Many thanks for your tutorial et your script & really sorry for my English ;)

    best regards


  • Hello

    I’ve some trouble with your script !

    I added a shadowbox and it worked perfect (at start) but Now that I have many more references (image) and I have some bugs with the link.

    It doesn’t open the good image (in shadowbox) when I click on item ???

    Some Idea ???