March 8, 2016 | 26 Feedbacks

Products Comparison Table

A responsive table to compare and filter through multiple products.
Browser support
  • ie
  • Chrome
  • Firefox
  • Safari
  • Opera

If you’re developing an online store with plenty of products, in all likelihood you’ve been asked to work on this feature: the comparison table. The standard approach, that works in most cases, is to use a simple HTML table element. If you have 6+ products to compare, though, things can get tricky, particularly when you try to make the whole thing responsive.

With today’s resource we wanted to provide a time-saver comparison table, specifically designed for big online stores. Our inspiration is the comparison tool we found on the beautifully designed Sony UK website. In terms of UX though, instead of letting users remove products from the list, we let them select, and filter, the ones they want to compare.

Creating the structure

The HTML structure is composed of a wrapping a <header> and a The <header> contains the action buttons (filter and reset) while the is used to wrap the div.features (product features list) and the The latter contains an unordered list ( for the product list items.

Adding style

The .cd-products-wrapper has a width of 100% and overflow-x of auto; the .cd-products-columns, instead, has a width equal to the sum of all columns widths and is scrollable (because of its parent overflow property). The div.features has an absolute position and is fixed on the left side of the viewport.

On big devices (viewport width greater than 1170px), the .top-fixed class is added to the .cd-products-table when user scrolls down to fix the products top information (product name and image):

Events handling

To implement the products table, we created a productsTable object and used the bindEvents function to attach event handlers to the proper elements:

You may have noticed that we added an event listener to the scroll event of the .cd-products-wrapper; when the .top-fixed class is added to the .cd-products-table, the .top-info elements are in fixed position, so they don’t scroll with the .cd-products-columns. The updateLeftScrolling() function is used to horizontally translate these elements while the user scrolls inside the .cd-products-wrapper.


Mar 08, 2016
  • Resource released by CodyHouse

Sebastiano Guerriero

UI/UX designer, with a huge passion for Nutella. Co-Founder of CodyHouse. You can follow him on Twitter or Dribbble.

  • Boba Fett

    This is great. You guys are amazing. It works for me (except the # of stars stays the same -; ) Keep up the great work

    • Sebastiano Guerriero

      Thanks Boba!

      • Boba Fett

        Sebastiano: It seems that my installation shows 5 stars for rating all the time !!!! I can not make it3 or 4 stars.

        • Sebastiano Guerriero

          the rating section is just a placeholder. We didn’t develop a “real” rating system, for we thought it was out of the focus of the resource

          • Boba Fett

            Fair enough….It makes no difference to me. I was just happy that I was able to make it work with my limited knowledge.

            BTW I just recommended your site to Weebly folks to add you as a resource along with Manoela’s site. I will let you know.

  • Wahyudies

    Awesome….. nice trick for small screen.

  • Stuart

    Visually (and in its responsive behaviour) it’s really nice. But it’s not actually a table, unfortunately (the row ‘headings’ don’t relate to the row content). Sorry if that sounds bitter, but I am always on the lookout for a nice responsive table

    • Boba Fett

      what r u talking? you can change the headings and make it related to row content….

      • Stuart

        you can do what you like with the text, but there is still no relationship between headings and the content in the way that there is in an actual table. From a structural perspective, this information is important; from an accessibility perspective, it can be very important indeed.

        • Boba Fett

          Perhaps I am retarded, but I have no clue of what you are talking about. The way I look at it from a user perspective is the information is easy to understand? does it look pretty? is it easy to navigate? From a code perspective is the code easy to modify? If the answers are yes, then the tutorial does its job.

          If you think you have better mousetrap, publish it for free and see what reaction you get with your ‘inventive’ solution. There are many paths one can take to go from point A to B. If you don;t like it does not mean people who take that road are ignorant.

          It is great because of the simple way the structure is presented. A novice like me can understand how things are done. A solution is elegant only if vast number of users can understand.

          If my comments are bitter, I mean them.

          • Stuart

            Hey mate, I think you’re missing my point. As I said, this is a really nice solution, but it’s not a table. I am constantly on the lookout for responsive tables, because presenting tabular data (such as product comparisons or checkout baskets) on mobile in an engaging, usable manner is still something that needs to be achieved. Just because it looks nice or is easy for the developer to achieve does not – IMO – mean that we should forego meaningful structure, because that is an essential part of HTML: a heading is marked up as a heading element, a paragraph as a paragraph element, a list as a list element, and a table as a table element.

            Unlike the fantastic guys at codyhouse, I don’t have time to work on this myself right now, hence my search for a solution (actually, I have seen a good candidate that I will post a link to later) – my only point was to point out that this solution, although it LOOKS like a table, is not actually a table.If you are happy with that, and can tie headings to the data semantically, then this is a good solution for your use case

          • Stuart

            For example, this is one of the nicest responsive tables I’ve seen

            It works nicely and it’s an actual table. But as with all things, it depends upon your needs/requirements. And it’s not so visually appealing as the codyhouse solution (but that could be changed easily enough).

          • KillaRizzay

            Dude, chill the F out. I can tell that you are indeed a novice who hasn’t worked on any large-scale projects because there’s validity in what Stuarts saying; some of us have to think about accessibility standards. To Stuart’s point, without the relationship of certain elements, things like Screen Readers for the blind can break. That’s why there are ARIA attributes you can add to custom elements (such as a custom built drop down, or in this case, a custom table) which instruct Screen Readers how to interpret a custom element and fill-in the necessary relationships of child elements.
            That said, I think the responsive comparison chart an elegant solution; it just falls short in the area of accessibility and that’s alright if you don’t have any accessibility requirements to adhere to. So next time you feel the urge to jump down the throat of someone pointing out something you don’t understand, stop and remind yourself that there developers out there that know more than you that also may have different requirements for their projects than you, then proceed to discuss and ask for elaboration like a mature adult with some humility instead of attacking them.
            I could lay into you like you did to Stuart for your ignorance of accessibility, but I won’t because there was a time I didn’t know either….stop being a douche..

          • Boba Fett

            Empty drums make the loudest noise – a Chinese Proverb

            criticizing someone’s work or slamming on people you may think you are
            superior, but that feeling is like pissing in a dark pant. It may give
            you a warm feeling, but no one else notices it !!

          • KillaRizzay

            Trust me, that wasn’t me slamming you…funny you bring that up after slamming the other guy though…

          • KillaRizzay

            FYI, this is the accessibility guideline I was referring to:

            This is a Level A guideline from the Web Content Accessibility Guidelines (WCAG) 2.0 which virtually any new website is to conform to. In short, virtually any custom UI control/element is to use ARIA attributes to denote it’s name and role to things like screen readers.

  • Михаил Подрабинек

    what fix do you suggest if one cell in a row has two lines of text, and others have only one line? This two-lines-of-text cell makes this table look ugly (height of a cell increases)

    • Alem Šabić

      Same question here, would be nice to have an answer to that.

      • Joshua Andrew Jourdain

        messy on disqus:

        function hideTable(){

        var table = $(‘.cd-products-table’);

        table.fadeTo(0, 0);



        function showTable(){

        var table = $(‘.cd-products-table’);


        table.fadeTo(300, 1);



        function setCellHeights(heights){





        //manage height of table cells




        var listCells = ”;

        var firstLiChildren = ”;

        var numberOfRows = ”;



        //second attempt


        //first gather all instances of class

        listCells = $(‘.cd-features-list’);




        var li = $(value).find(‘li’);







        //then gather children of first instance

        firstLiChildren = $(listCells[0]).children();


        //use first instance to determine number of rows needed

        numberOfRows = firstLiChildren.length;


        //create array of heights

        heights = [];


        //populate array of heights with first instance heights

        $.each(firstLiChildren, function(index,value){


        //value.offsetHeight = 0;

        var indexObject = {

        index: index,

        value: value,



        //push object to heights array




        //compare each subsequent instance of class in for loop

        $.each(listCells, function(index,value){


        //reset all heights to auto

        //start after first instance

        if(index > 0){

        //do for loop of li child elements here

        $.each($(value), function(i,v){

        //interior for each

        $.each($(v).children(), function(jindex, wvalue){

        if(heights[jindex].height < $(wvalue).prop('offsetHeight')){

        heights[jindex].height = $(wvalue).prop('offsetHeight');







        //make cells the height specified

        $.each(listCells, function(index, value){

        $.each($(value).children(), function(i,v){








        delay : 250

        }, function() {

        // …



  • Isabella Betkowski

    Thanks for sharing. Do you guys have any good suggestions for complex pricing tables where buying multiple products/in certain combinations gives the user a discount? Thanks.

  • Peak Usability

    Am I missing something? Looking at the Sony URL and trying to find a compare function or comparison tool but cant find it anywhere on the site. Keen to see the example.

  • Dani Ivanov

    Hmmm… doesn’t seem to work when I try to copy the code. Here is a codepen

  • dubplatsa

    Great solution! I’ll try to “rotate” the table (put the products in the first column) – hopefully I can!

  • Edson Romero

    doesn’t work for me either :( trying to place it in wordpress root folder but no go. Looking same as Dani Ivanov example. Help?

  • David Klotz

    Great solutions for product comparisons and thank you for sharing it! I am running into one issue with the fixed top info on scroll. This works flawlessly if the comparison table is the full width of the viewport, however if set inside a container, overflow-x does not remain hidden exposing the fixed bar left and right of the table. Is it possible to achieve this with fixed position or do I need to make a compromise and make the comparison table full width or remove the fixed top info positioning?