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:

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.

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

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

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

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>

Let’s break down the code for more details.
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.

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

However, the buttons haven’t worked. We need to use some JavaScript.
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' );
}
} );
}
} );
} );
} );

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:
- All the old data in rows and their style will be reset to be overridden by the new data based on the selected products.
- The table includes rows that are specifications of the product, and they are filled in with data from the corresponding fields.
- 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.

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.
- MB Views: How To Display Relationships?
- How to Create Reusable Template Parts in WordPress
- How to Create YouTube Video Timestamps on WordPress Website - P1 - Using MB Views
- How to Randomize Hero Image in WordPress - Using MB Views
- How to Display a Video Playlist - Using MB Views
- How to Create a Reading Progress Bar in WordPress Posts - P1 - Using MB Views
- How to Create Reading Time to Your WordPress Posts - Using MB Views
- How to Add Code to Header and Footer in WordPress - Using MB Views
- How to Create Charts in Posts - Using MB Views
- How to Create a Dynamic Horizontal Posts Accordion - Using MB Views
- How to Manage & Display Course Schedule With Filters
- How to Create the Rating Feature for a WordPress Website - Using MB Views
- How to Create a Product Comparison Table - Using MB Views
- Author Bio
- Better 404 Page
- Blogs for Developers
- Building a Simple Listing Website with Filters
- Building an Event Website
- Building Forms with MB Frontend Submission
- Coding
- Create a Chronological Timeline
- Custom Fields Fundamentals
- Design Patterns
- Displaying Posts with Filters
- Download and Preview Buttons
- Dynamic Banners
- Dynamic Landing Page
- FAQs Page
- Featured Products
- Filter Posts by Relationships
- Filter Posts by Taxonomy
- Full Site Editing
- Google Fonts
- Gutenberg
- Hotel Booking
- Latest Products
- Logo Carousel
- MB Builder Applications
- MB Group Applications
- MB Views Applications
- Most Viewed Posts
- Opening Hours
- OTA Website
- Pricing Table Page
- Product Page
- Product Variations
- Querying and Showing Posts by Custom Fields
- Recipe
- Related Posts via Relationship
- Restaurant Menus
- SEO Analysis
- Simple LMS
- Speed Up Website
- Taxonomy Thumbnails
- Team Members
- User Profile
- Video Gallery
How to Create a Pricing Table Page - P3 - Using MB Views
How to Display Before and After Images - Using MB Views
MB Views vs. Dynamic Shortcodes: More Similarities than You Realized