Grow your CSS skills. Land your dream job.

Filtering Blocks v2

Published by Chris Coyier

This is an update to the first version of filtering blocks I did a while back. The idea is that you have a long list or large set of "blocks" on the page. Each block belongs to a certain group. There is navigation on the page for viewing all of them at once, or selecting which group you would like to see. Selecting a particular group hides the blocks from any other group, hence "filtering".

 

View Demo   Download Files

 

HTML

Each block has class names applied to it for the groups it belongs to. Here are two examples. The both belong to the group "all", the top one "adv" and the bottom one "cla".

<div class="all adv">
<img src="images/flavor-curry.jpg" alt="" />
<h4>Sweet Curry With Saffron</h4>
<p>Lusciously mellow with notes of overripe berries, 55% Hawaiian dark chocolate meets its soulmate in sweet curry - awash in spices including coriander, tumeric, cumin and cardamom and sprinkled with rare saffron. This spicy melange is slowly steeped in fresh coconut puree and gently blended with the chocolate. The taste rushes over you in waves - fragrant curry, chased by coconut, then the lingering, raisiny sweetness of chocolate. Available in <a href="/store/products/Chocolatier_s_Choice-5-2.html">Chocolatier's Choice</a> and <a href="/store/products/Adventurous_Collection-3-2.html">Adventurous Collection</a>.</p>
</div>

<div class="all cla">
<img src="images/flavor-vanilla.jpg" alt="" />
<h4>Lucille's Vanilla </h4>
<p>For those who prefer milder chocolate, this winsome truffle will ignite a lifelong love affair. Gail uses a dark blend in this recipe handed down through four generations of the Guittard family of chocolate makers. It tastes like a rich spoonful of homemade chocolate pudding - just like Gail's mom, Lucille, made on the stovetop in their family farm's kitchen. Available in <a href="/store/products/Chocolatier_s_Choice-5-2.html">Chocolatier's Choice</a> and <a href="http://gailambrosius.com/store/products/Classic_Collection-2-2.html">Classic Collection</a>.</p>
</div>

Then the navigation includes REL attributes that reference those classes:

<div id="flavor-nav">
    <a rel="all" class="current">All</a> 
    <a rel="cla">Classic</a> 
    <a rel="adv">Adventurous</a> 
    <a rel="tea">Tea-Inspired</a> 
</div>

jQuery JavaScript

The plan in plain English:

  1. When a link in the filtering navigation is clicked...
  2. Fade down all blocks (visual indication something is changing)
  3. Remove "current" class from all navigation and apply it to newly clicked navigation
  4. Figure out which group should be showing from the REL attribute
  5. Any flavor NOT a part of the group, slide up
  6. Any flavor that IS a part of the group, slide down
  7. Fade back up all blocks
$(function() {

	var newSelection = "";
	
	$("#flavor-nav a").click(function(){
	
	    $("#all-flavors").fadeTo(200, 0.10);
	
		$("#flavor-nav a").removeClass("current");
		$(this).addClass("current");
		
		newSelection = $(this).attr("rel");
		
		$(".flavor").not("."+newSelection).slideUp();
		$("."+newSelection).slideDown();
		
	    $("#all-flavors").fadeTo(600, 1);
		
	});
	
});

This leads to a smoother experience than we had in version 1. Primarily because of the use of the .not() native jQuery filter. Before, we just "slid up" all the flavors and then "slid down" the correct ones. That means that every single flavor went through animation on every single navigation change. But that isn't always necessary. For example if you are viewing one sub-set, then click back to "all", those currently showing blocks don't need to be animated, just all the other ones need to grow out. This solves that.

Comments

  1. Permalink to comment#

    Nice example thank you a lot chris

  2. I heart jQuery. Thanks bro.

  3. cursor:pointer;

  4. It’s nice, I just hate clickable things that don’t have cursor:pointer.

    Would it look better if the rest of the code was a callback to the fadeTo(), so everything moves after the fade has completed? To me it looked a bit weird for everything to be sliding up over things that hadn’t disappeared yet…

  5. Great stuff, as always!

  6. Permalink to comment#

    Two things:

    1) I really feel like that whole thing should be in an unordered list. Semantically correct and just better markup, I think.

    2) Check out the new Special K site where I did the same thing to sort recipes.

  7. blanchimont
    Permalink to comment#

    thx great tutorial !

  8. Permalink to comment#

    I did a similar thing on our fin page, but i like how your code uses the same function for each click.

    I also used CSS to hide other items if the user doesn’t have JS enabled.

  9. jsdev
    Permalink to comment#

    I agree with Skilldrick’s two comments.

    I would add two more, but first want to say this is a great site I’ve been following for awhile.

    1) I would discourage using “all” class name and for that purpose used here. I would instead recommend not filtering, unfiltering.

    2) I recommend having the hover state look slightly different than the selected state, because if you have two orange box categories, despite cursor pointer or not, it could confuse user unnecessarily

  10. Permalink to comment#

    Ohh!! What i was looking for!! Tnks!!

  11. Permalink to comment#

    Nice technique, Chris. I do something similar for our in-house Sales Order app, using Rik Lomas’ excellent QuickSearch jQuery plugin. This allows you to setup your “block” links, as well as a filtering input field matching any text (like iTunes, et al).

  12. Jason
    Permalink to comment#

    Something about it bugs me, but I can’t put my finger on it. It might be what Skilldrick was saying.
    When clicking between classic and adventurous, the scrollbar will shrink slowly then jump again. The jump just doesn’t seem right.

  13. Sweet!

  14. Nice, but it doesn’t work with JavaScript disabled. You still get the navigation links at the top but clicking on them does nothing.

    Perhaps another implementation is to code up everything into individual sections:

    Classic
    whatever…

    Adventurous
    whatever…

    etc.

    Then with JavaScript, generate your top nav by looping through all h3s to grab the innerHTML content, link them to internal anchors (the h3s), hide the h3s down in the body and do the JS show/hide/filter.

    It works “old-school” style with no JavaScript, works fancier with JavaScript.

    • Yep, that’s a good idea. Or perhaps just add the navigation with JavaScript. Without just lists everything. (or unhide nav when JS loads)

    • Permalink to comment#

      Who use browsers with Javascript disabled? We should move forward with this…

    • WMuse
      Permalink to comment#

      @iPad

      There are many cases in which Javascript may be disabled for compatibility with with some accessibility devices for the purpose of site interaction or hardware based screen reader as oppose to one being software driven on a full computer.

      Another case is where not everyone is on a newer mobile device that may not fully support javascript so having things degrade nicely with things turned off increases the sites viewership in some situations.

      Looking at it realistically even in small percentages the number of people can easily be more then 50,000+ potential viewers that you’re simply going to miss out on. This is of course all entirely relative to the intended audience of your content as well.

      Don’t underestimate the amount of people out there though that really need the content to degrade properly to be able to experience it.

  15. Permalink to comment#

    Looks Great… I think it will look cooler if you disable the fade in and out !

    Like one at Special K.

    Good JoB!

  16. Permalink to comment#

    .flavor {
    background:#EDEDED none repeat scroll 0 0;
    border:1px solid #DEDEDE;
    clear:both;
    margin:0 0 15px;
    overflow:hidden;
    }

  17. Thank God, this is just what I needed for a WP gallery solution.

  18. Josh
    Permalink to comment#

    Hmm…. why does this not work for me in Firefox (3.0.10)?? Even worse… it’s work in IE! ahhh! The world is ending!

    But seriously…. any ideas?

  19. Ben
    Permalink to comment#

    I have an idea for v3.

    Lets say the list is dynamic and is using pagination and has a limit of say 10 items.

    And when I filter out some and are left with 3 items or whatever, it would grab 7 other items from the DB to make up.

    I’d really like to see that.

    And nice post, this is the only good web development blog left.

    • That’s pretty viable. The JS would just need to know the pagination number. Then, once the items are filtered, logic checks whether the number displayed is smaller than the limit. If it is, perform an AJAX call to the server-side with a param to return (limit – num) items. The data that is returned is then added to the set.

  20. Permalink to comment#

    Really interesting, could be pretty usefull integrated into wp.

  21. Permalink to comment#

    Great, thanks for this. I’m using the first version for my http://www.nathanbweb.com, but I’ll consider revising.

  22. Ant
    Permalink to comment#

    Yeah, I did similar thing today, but with select.
    Design with tabs is better and more usable.

  23. Yong
    Permalink to comment#

    It doesn’t work with Videobox v.1.1 :-(

    http://www.networkworking.com/media_placements.html

  24. Nico
    Permalink to comment#

    When you apply this filter effect with Masonry it does not reshuffle the deck on-click, anyone else with this issue?

This comment thread is closed. If you have important information to share, you can always contact me.

*May or may not contain any actual "CSS" or "Tricks".