Grow your CSS skills. Land your dream job.

Filtering Blocks

Published by Chris Coyier

One of our eCommerce clients at work had a number of products they wanted to put on special to promote on the web. Each product has a different "reason" why it's on special. Perhaps it's discontinued, perhaps its special pricing, perhaps it's free shipping. Originally they wanted a special page built for a new type of discount: "rollback pricing". We argued that in general, a visitor on the web doesn't really care why a product is on sale, just that it is, and that it may be of disservice to split up the specials page into different pages.

Instead, we compromised on leaving the specials page as a single page, but allowing the products within to be viewed all at once, or filtered by the type of special that it is. A little jQuery is always up for the job!

 

View Demo   Download Files

 

The Markup

Each block has a wrapping div. It has one class that it shares with all other blocks for common styling and a class unique to its "type". Div's don't have href elements, but they can have rel attributes, which I used to store a URL. In the demo, div clickablility isn't implemented, but the code is just commented out in the JavaScript, so you can see how to make that happen there.

<div class="discounted-item reduced" rel="/store/catalog/Dryline_Markers-47-1.html">

    <img src="images/discountthumb-streamliner.jpg" alt="streamliner" />
    
    <div class="reasonbar">
        <div class="prod-title">Streamliner Field Chalkers</div>
        <div class="reason">Rollback Pricing</div>
    </div>

    <div class="discount-bar">
        Price lower than catalog. Save $30!
    </div>

</div>

The "filtering" menu is just a series of links. Each link has an ID that matches the class of the type it intends to filter by:

<p id="catpicker">
<a href="#" id="allcat" class="current">VIEW ALL</a> | 
<a href="#" id="reduced" class="filter">Rollback Pricing</a> | 
<a href="#" id="freeshipping" class="filter">Free Shipping</a> | 
<a href="#" id="discontinued" class="filter">Closeout</a> | 
<a href="#" id="webonly" class="filter">Web Only</a>
</p>

The CSS

There is nothing too tricky going on in the CSS, but I'll drop it in here just for good measure.

*                           { margin: 0; padding: 0; }
html                        { overflow-y: scroll; }
body                        { font: 12px Georgia; }

#page-wrap                  { width: 690px; margin: 20px auto; }

h1                          { font: 30px Georgia; margin: 0 0 10px 0;  }

.discounted-item            { width: 100%; margin: 0 0 10px 0; position: relative; cursor: pointer;
                              height: 79px; }

.discount-bar               { padding: 10px 0 10px 150px; font: italic 18px Georgia, Serif; }

.reasonbar                  { padding: 4px 0 4px 150px; overflow: hidden;
                              width: 540px; color: white; }
                 
.prod-title                 { width: 49%; float: left; font: bold 17px Helvetica, Sans-Serif; }
.reason                     { width: 49%; float: right; text-align: right; text-transform: uppercase; 
                              letter-spacing: 2px; padding: 0 5px 0 0; }
                              
.discounted-item img        { position: absolute; top: 0; left: 0; }

.reduced                    { border: 2px solid #A34427; }
.reduced .reasonbar         { background: #A34427; }
.reduced .discount-bar      { color: #A34427; background: white; }

Random things of note:

  • Because the height of the page grows and shrinks, it's best to force a vertical scrollbar to avoid jumps in horizontal centering.
  • Image was placed with absolute positioning. Easy and sturdy layout technique for this, with no floats.
  • Div's have a pointer cursor applied, since in a live scenario they would be clickable.

The jQuery JavaScript

Added a little opacity-rollover action. (Also, this is the area you could make the div's clickable, see the actual JS in the example).

$(".discounted-item")
        .css("opacity","0.8")
       .hover(function(){
           $(this).css("opacity","1");
       }, function() {
           $(this).css("opacity","0.8");
});

And to make the filtering work:

$("#allcat").click(function(){
       $(".discounted-item").slideDown();
       $("#catpicker a").removeClass("current");
       $(this).addClass("current");
       return false;
});
   
$(".filter").click(function(){
        var thisFilter = $(this).attr("id");
        $(".discounted-item").slideUp();
        $("."+ thisFilter).slideDown();
        $("#catpicker a").removeClass("current");
        $(this).addClass("current");
        return false;
});

Slightly different code for the "View All" button, since all it has to do is reveal everything.

In the live demo, there is also some "shuffling" going on, so that the order of the specials is randomized on every page load thanks to James Padolsey's DOM shuffler.

Similar Tutorial

Trevor Davis did a very similar demo on NETTUTS a while back.

Comments

  1. Permalink to comment#

    If you don’t want it randomized, but alphabetically ordered, how do you achieve that in jQuery? It’s a very nice touch to have them laid out like cards too.

    • It’s in the filter.js file. Delete the first line until the })(jQuery); . Then near the bottom $(“.discounted-item”).shuffle();. By my count it’s lines 1-24 and then line 60.

  2. that is quite sweet, I wish I knew jQuery

  3. Thanks for this little block, it work’s pretty well. Only have one question and I’m not sure if this isn’t out of the realm of this article. I was trying to integrate something like this into wordpress. I was using an additional plugin to match to create an infinite scroll(also the name of the plugin) of content so that when the user reaches the end it grabs more. I would be using it in a very similar way to your example as well. The problem is, when it fetches more it doesn’t come filtered, it just has the next page worth of content. Is there a jQuery function (I suck with programming in general) or something that I can use to pass that on to the new results without having the person click the filter choice again. Thanks

  4. Samuel
    Permalink to comment#

    This is awesome. Thanks for sharing!

  5. Interesting, has some possibilities for future projects.

  6. Matthew V
    Permalink to comment#

    You know what guys. I could see this being a GREAT plugin for wordpress to sort through categories! But I don’t know php, so don’t ask me lol.

  7. Pretty cool Chris. I guess my only gripe is that it doesn’t gracefully degrade. Turn off JavaScript and none of the navigation links, link to anything. I would recommending appending them with JavaScript and displaying all by default.

  8. Raiven Thrones
    Permalink to comment#

    Cool!I wish i know JQuery … uhm… i hope you could write a tutorial about JQuery? I mean I saw your video tutorial about JQuery and I realy liked it and its pretty cool. It seems easy … but could you just make more tutorial about JQuery. Thanks a lot … this is great!

  9. Permalink to comment#

    This is sweat! Thanks, Chris.

  10. fanis papadopoulos
    Permalink to comment#

    hello chris from GREECE
    thank for your tutorials .
    I try to test the Filtering Blocks offline but the filtering don’t work????
    Please informe what is my wrong ???
    thank you
    fanis

  11. Jon
    Permalink to comment#

    is there anyway it is possible to filter the list onload? instead of showing all records by default? thanks and great script…

  12. marc

    you can hide what you don’t want to show by applying a “display: none” to that div item.. however the “view all” is still set to “current” instead of the div item you want to display onload.. changing the “view all” div ID from “current” to “filter” scrrew it up…

    anyone know?

  13. This is a great tutorial – I’m going to give this one a try.

  14. Assam
    Permalink to comment#

    How would I use this with MYSQL?

    I have a while loop that echoes out a list of football games and want to use the filter to sort through competitions, years and seasons etc

    Where would I begin?

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".