Black Friday 2025
Meta Box

How to Create a Product Comparison Table - Using MB Views

A product comparison table gives a clear overview and helps them make decisions easily, instead of having to remember and compare everything themselves. Therefore, it will be an incredibly practical feature, no matter what type of tangible product or service you’re offering.

In this blog post, we want to introduce the way to create a product comparison table with the help of MB Views from Meta Box, including advanced features such as:

  • Adding products for comparison
  • Creating the table along with specifications as points of comparison
  • Highlighting the needed data.

For demonstration purposes, I will compare several mobile phones on an archive page. And this is our expected result:

The example of product comparison table.

This approach is useful in many cases, since beyond the price, buyers always want to compare other details to make sure they choose exactly what they need. For example, they might compare the contents of online courses, the services of different hotels, the specifications of cars from various brands, or the amenities of real estate listings.

This type of table is good for enhancing user experience, increasing traffic, and boosting your conversions.

Video Version

Before Getting Started

All of the specifications are stored in custom fields to identify each item and compare them easily. So, basically, our aim is to display and compare the field values across different posts.

For the needed tools for this practice, we highly recommend you use Meta Box AIO to have both the framework and advanced features from all the Meta Box extensions. These are extensions we use to have a product comparison feature:

  • MB Custom Post Type: to create a custom post type for products.
  • MB Views: to create a view for displaying data and creating a comparison table.
  • MB Builder: to have UI in the backend to create custom fields visually.

I skip some basic steps, such as creating custom post types, custom fields, and templates for displaying data from the fields, to save time. If you don’t know how to create them yet, you should check out our previous tutorials on the YouTube channel or blog page.

I have created a custom post type for the product.

The created custom post type

Also, we have a field group to store extra information. You can change the field types and their settings as you need.

The created field group

I input data for each post as well. And, a ready template for displaying data and styling the archive page of products.

The created view

After showing data, we have a page on the frontend as below:

The archive page on the frontend

Now, we’ll focus on how to create the comparison table for this page.

Create the Comparison Feature for the Page

Back to the mentioned template to add some code.

First, we’ll use the JavaScript library for creating the comparison table. So, I add a line of code to declare it.

<script src="https://code.jquery.com/jquery-3.7.1.min.js"></script>

Next, for the features of the comparison table, I add this code:

            <button class="btn-compare"
                 data-id="{{ post.ID }}"
                 data-title="{{ post.title }}"
                 data-thumb="{{ post.thumbnail.full.url }}"
                 data-os="{{ post.operating_system }}"
                 data-cpu="{{ post.processor }}"
                 data-storage="{{ post.storage.value }}"
                 data-camera="{{ post.camera }}"
                 data-battery="{{ post.battery.value }}">
                 + Compare
            </button>
        </div>
    {% endfor %}
</div>

<div id="compare-bar">
    <div class="compare-slots">
        <div class="slot" data-slot="1">+ Add Product</div>
        <div class="slot" data-slot="2">+ Add Product</div>
        <div class="slot" data-slot="3">+ Add Product</div>
    </div>
    <button id="btn-show-compare" disabled>Compare Now</button>
    <a href="#" id="btn-clear-all">Clear all products</a>
</div>

<div id="compare-table-container" style="display:none;">
    <h2>Compare Table</h2>
    <table class="compare-table">
        <thead>
            <tr id="compare-titles">
                <th>Technical Specifications</th>
            </tr>
        </thead>
        <tbody>
            <tr id="row-os"><td>Operating System</td></tr>
            <tr id="row-cpu"><td>CPU</td></tr>
            <tr id="row-storage"><td>Storage</td></tr>
            <tr id="row-camera"><td>Camera</td></tr>
            <tr id="row-battery"><td>Battery</td></tr>
        </tbody>
    </table>
</div>

Add some code to create the comparison feature

Let’s break down the code for more details.

Adding Compare Buttons to Add the Product to the Table

At the bottom of each product card, we’ll add a Compare button thanks to this part of code:

<button class="btn-compare"
    data-id="{{ post.ID }}"
    data-title="{{ post.title }}"
    data-thumb="{{ post.thumbnail.full.url }}"
    data-os="{{ post.operating_system }}"
    data-cpu="{{ post.processor }}"
    data-storage="{{ post.storage.value }}"
    data-camera="{{ post.camera }}"
    data-battery="{{ post.battery.value }}">
    + Compare
</button>

You should set a class for them for styling easily. In my case, it is btn-compare. The buttons include some attributes such as: data-id, data-title, data-thumb, data-os, data-cpu, data-storage, data-camera, and data-battery. All of them are assigned to the value of the corresponding fields.

My buttons have the label as +Compare. You can change it as you want.

Show the Selected Products for Comparison

We need a space to cover the products that we want to compare. So, I use this part.

<div id="compare-bar">
    <div class="compare-slots">
        <div class="slot" data-slot="1">+ Add Product</div>
        <div class="slot" data-slot="2">+ Add Product</div>
        <div class="slot" data-slot="3">+ Add Product</div>
    </div>
    <button id="btn-show-compare" disabled>Compare Now</button>
    <a href="#" id="btn-clear-all">Clear all products</a>
</div>

There will be up to 3 products that can be selected for comparison. You can add or reduce the number as you need, for example: only two products with two classes.

Under this space, we add two buttons. One is the Compare Now button to compare the selected products. And the other to clear them all.

Set up the Comparison Table

For the comparison table, I add these lines of code.

<div id="compare-table-container" style="display:none;">
    <h2>Compare Table</h2>
    <table class="compare-table">
        <thead>
            <tr id="compare-titles">
                <th>Technical Specifications</th>
            </tr>
        </thead>
        <tbody>
            <tr id="row-os"><td>Operating System</td></tr>
            <tr id="row-cpu"><td>CPU</td></tr>
            <tr id="row-storage"><td>Storage</td></tr>
            <tr id="row-camera"><td>Camera</td></tr>
            <tr id="row-battery"><td>Battery</td></tr>
        </tbody>
    </table>
</div>

The table is hidden by default, and only displays when you click on the Compare Now button that we created above. The table, along with the rows as specifications that are the value of the custom field you input before.

You should move to the CSS tab to style the selected product space and comparison table.

Add CSS to style the comparison table

After that, on the frontend, you can see there are these buttons in each product, and an area to show the compared product.

The buttons and table are displayed on the frontend

However, the buttons haven’t worked. We need to use some JavaScript.

Add Actions for Buttons and Comparison Table

Back to the template and navigate to the JavaScript tab to add an action for the button and comparison functionality.

jQuery( function ( $ ) {
    const $slots = $( '#compare-bar .slot' );
    const $btnCompare = $( '#btn-show-compare' );
    const $btnClearAll = $( '#btn-clear-all' );
    const $tableContainer = $( '#compare-table-container' );
    let selected = [];

    // Add product.
    $( '.btn-compare' ).on( 'click', function () {
        const id = $( this ).data( 'id' );

        if ( selected.length >= 3 || selected.some( function ( p ) { return p.id === id; } ) ) {
            return;
        }

        const product = {
            id: id,
            title: $( this ).data( 'title' ),
            thumb: $( this ).data( 'thumb' ),
            os: $( this ).data( 'os' ),
            cpu: $( this ).data( 'cpu' ),
            storage: $( this ).data( 'storage' ),
            camera: $( this ).data( 'camera' ),
            battery: $( this ).data( 'battery' )
        };

        selected.push( product );

        // Assign to an empty slot.
        $slots.each( function () {
            if ( ! $( this ).attr( 'data-filled' ) ) {
                $( this ).html(
                    '<img src="' + product.thumb + '" alt="' + product.title + '"><br>' +
                    product.title +
                    '<span class="remove" data-id="' + id + '">x</span>'
                );
                $( this ).attr( 'data-filled', id );
                return false; // Exit the loop.
            }
        } );

        $btnCompare.prop( 'disabled', selected.length < 2 );
    } );

    // Remove product from slot.
    $( '#compare-bar' ).on( 'click', '.remove', function () {
        const id = $( this ).data( 'id' );

        selected = selected.filter( function ( p ) {
            return p.id !== id;
        } );

        $slots.each( function () {
            if ( $( this ).attr( 'data-filled' ) == id ) {
                $( this ).html( '+ Add Product' ).removeAttr( 'data-filled' );
            }
        } );

        $btnCompare.prop( 'disabled', selected.length < 2 );
    } );

    // Delete all products.
    $btnClearAll.on( 'click', function ( e ) {
        e.preventDefault();

        selected = [];
        $slots.html( '+ Add Product' ).removeAttr( 'data-filled' );
        $btnCompare.prop( 'disabled', true );
        $tableContainer.hide();
    } );

    // Show comparison table.
    $btnCompare.on( 'click', function () {
        if ( selected.length < 2 ) {
            return;
        }

        $tableContainer.show();

        // Reset table (delete old header / old rows / highlight).
        $( '#compare-titles' ).html( '<th>Technical specifications</th>' );
        $( '#row-os' ).html( '<td>Operating System</td>' );
        $( '#row-cpu' ).html( '<td>CPU</td>' );
        $( '#row-storage' ).html( '<td>Storage</td>' );
        $( '#row-camera' ).html( '<td>Camera</td>' );
        $( '#row-battery' ).html( '<td>Battery</td>' );
        $( '.compare-table .highlight' ).removeClass( 'highlight' );

        // Render the selected product.
        $.each( selected, function ( i, p ) {
            $( '#compare-titles' ).append( '<th>' + p.title + '</th>' );
            $( '#row-os' ).append( '<td class="field-value">' + ( p.os || '' ) + '</td>' );
            $( '#row-cpu' ).append( '<td class="field-value">' + ( p.cpu || '' ) + '</td>' );
            $( '#row-storage' ).append( '<td class="field-value">' + ( p.storage || '' ) + '</td>' );
            $( '#row-camera' ).append( '<td class="field-value">' + ( p.camera || '' ) + '</td>' );
            $( '#row-battery' ).append( '<td class="field-value">' + ( p.battery || '' ) + '</td>' );
        } );

        // Highlight if there is a duplicate value (at least 2 products have the same value).
        $( '.compare-table tbody tr' ).each( function () {
            const $cells = $( this ).find( '.field-value' );

            if ( $cells.length > 1 ) {
                // build frequency map (normalize: trim + toLowerCase)
                const values = $cells.map( function () {
                    return $.trim( $( this ).text() ).toLowerCase();
                } ).get();

                const freq = {};
                values.forEach( function ( v ) {
                    if ( v === '' ) {
                        return;
                    }
                    freq[ v ] = ( freq[ v ] || 0 ) + 1;
                } );

                // apply highlight to any cell whose value appears >= 2
                $cells.each( function () {
                    const val = $.trim( $( this ).text() ).toLowerCase();
                    if ( val !== '' && freq[ val ] >= 2 ) {
                        $( this ).addClass( 'highlight' );
                    }
                } );
            }
        } );
    } );
} );

Add JavaScript for the actions of the comparison table.

It’s time to explore the meaning of each part of the code.

Before adding actions for features of the comparison table, we need to initialize variables that are used for the comparison table, including:

  • $slots: is for placeholders for selected products.
  • $btnCompare: is for the Compare buttons.
  • $btnClearAll: is for the Clear All button.
  • $tableContainer: is for the comparison table.

I also create an array that contains the selected products.

Adding Products to Compare

// Add product.
    $( '.btn-compare' ).on( 'click', function () {
        const id = $( this ).data( 'id' );

        if ( selected.length >= 3 || selected.some( function ( p ) { return p.id === id; } ) ) {
            return;
        }

        const product = {
            id: id,
            title: $( this ).data( 'title' ),
            thumb: $( this ).data( 'thumb' ),
            os: $( this ).data( 'os' ),
            cpu: $( this ).data( 'cpu' ),
            storage: $( this ).data( 'storage' ),
            camera: $( this ).data( 'camera' ),
            battery: $( this ).data( 'battery' )
        };

        selected.push( product );

        // Assign to an empty slot.
        $slots.each( function () {
            if ( ! $( this ).attr( 'data-filled' ) ) {
                $( this ).html(
                    '<img src="' + product.thumb + '" alt="' + product.title + '"><br>' +
                    product.title +
                    '<span class="remove" data-id="' + id + '">x</span>'
                );
                $( this ).attr( 'data-filled', id );
                return false; // Exit the loop.
            }
        } );

        $btnCompare.prop( 'disabled', selected.length < 2 );
    } );

This means when you click on the Compare button at the end of a product, the ID of that product will be retrieved. Then, there will be two possible cases:

If there are 3 products, or the same product has been selected already, that product will not be added to the slot.

Otherwise, an object product is created that covers all the details of the product, including custom fields.

Then, the next part of the code is to add that product to the empty slot. For each selected product, the slot will show the thumbnail, title, and a remove button.

And, the Compare Now button is only clickable when there are at least 2 selected products.

Remove Product from Slot

To do it, we use the next part of code.

We’ll remove the product via its ID as well. After that product is removed from the slot, disable the Compare button if fewer than two products remain.

Delete All Products

$btnClearAll.on( 'click', function ( e ) {
    e.preventDefault();

    selected = [];
    $slots.html( '+ Add Product' ).removeAttr( 'data-filled' );
    $btnCompare.prop( 'disabled', true );
    $tableContainer.hide();
} );

When you click on the Clear All button, everything will be back to the default mode. It means the selected product slot is empty, the Compare Now button is disabled, and the table is hidden.

Show the Comparison Table

The table will display when we click on the Compare Now button. And there will be three actions run. They are:

  1. All the old data in rows and their style will be reset to be overridden by the new data based on the selected products.
  2. The table includes rows that are specifications of the product, and they are filled in with data from the corresponding fields.
  3. The same data is highlighted.

The logic is looping through data in rows, detecting and highlighting all the same data. In the real case, you can also bring out the different data in a row so that the customer can pay attention to the differences.

That’s all.

Now, let’s view the page on the frontend, and try to check how it works.

The final result of product comparison table.

As you can see, the specifications are displayed in the comparison table, and the same data is highlighted. The code works well when you want to compare three products.

Last Words

With MB Views, you get full control over the logic, layout, structure, and data you want to display for the product comparison table. As a result, creating that table with many advanced features has become easier than ever.

You can also explore the power of this extension from this source, where we provide more examples, use cases, and best practices to help you get the most out of MB Views.

Leave a Reply

Your email address will not be published. Required fields are marked *