✦ A decade of Canvas craft, now driven by AI — describe it, watch it build live.Start building
Bootstrap 5Content

Bootstrap 5 Comparison Table

A comparison table is a structured UI pattern that places two or more options side by side in a tabular layout so users can evaluate features at a glance. It is composed from Bootstrap 5's table utilities (.table, .table-bordered, .table-striped), sticky positioning, badge components, and flex utilities — Bootstrap ships none of this as a named component. Use it whenever a product, pricing, or feature decision benefits from a direct column-by-column contrast.

Primary Class

.table .table-bordered

Common Use Cases

  • A SaaS product page comparing Free, Pro, and Enterprise subscription tiers across a list of feature limits and support levels.
  • A hosting provider's documentation page contrasting shared, VPS, and dedicated server specifications such as CPU, RAM, and bandwidth.
  • An e-commerce site's buying guide placing three camera models side by side with sensor size, weight, and battery life values.
  • A government procurement portal displaying tender responses from multiple suppliers against a fixed set of evaluation criteria.

Variants & Classes

VariantDescription
Basic Feature ComparisonA plain bordered table with a sticky first column and tick/cross icons to indicate feature availability per plan.
Highlighted ColumnOne column is visually promoted with a background colour and a 'Most Popular' badge pinned to its header to draw attention.
Striped Responsive WrapperWrapped in a div with overflow-x-auto and table-striped so the table scrolls horizontally on small screens without breaking the layout.
Card-based Column LayoutInstead of a traditional table element, Bootstrap card and grid columns simulate a comparison layout for fully custom styling per plan.

Code Example

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>Pricing Comparison Table</title>
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css">
  <style>
    .comparison-table th:first-child,
    .comparison-table td:first-child {
      position: sticky;
      left: 0;
      background-color: var(--bs-body-bg);
      z-index: 1;
      border-right: 2px solid var(--bs-border-color);
      font-weight: 600;
    }
    .comparison-table thead th.col-highlight {
      background-color: var(--bs-primary);
      color: #fff;
    }
    .comparison-table tbody td.col-highlight {
      background-color: var(--bs-primary-bg-subtle);
    }
    .tick { color: #198754; font-size: 1.15rem; }
    .cross { color: #dc3545; font-size: 1.15rem; }
  </style>
</head>
<body class="py-5">
<div class="container">
  <h2 class="mb-1 fw-bold text-center">Choose Your Plan</h2>
  <p class="text-center text-muted mb-4">All plans include a 14-day free trial. No credit card required.</p>
  <div class="table-responsive">
    <table class="table table-bordered table-hover align-middle comparison-table">
      <thead class="table-dark">
        <tr>
          <th scope="col" style="min-width:200px">Feature</th>
          <th scope="col" class="text-center" style="min-width:140px">Free</th>
          <th scope="col" class="text-center col-highlight" style="min-width:140px">
            Pro
            <span class="badge bg-warning text-dark ms-1">Popular</span>
          </th>
          <th scope="col" class="text-center" style="min-width:140px">Enterprise</th>
        </tr>
      </thead>
      <tbody>
        <tr>
          <td>Monthly price</td>
          <td class="text-center">£0</td>
          <td class="text-center col-highlight fw-semibold">£19</td>
          <td class="text-center">£79</td>
        </tr>
        <tr>
          <td>Team members</td>
          <td class="text-center">1</td>
          <td class="text-center col-highlight">Up to 10</td>
          <td class="text-center">Unlimited</td>
        </tr>
        <tr>
          <td>Storage</td>
          <td class="text-center">5 GB</td>
          <td class="text-center col-highlight">50 GB</td>
          <td class="text-center">1 TB</td>
        </tr>
        <tr>
          <td>Custom domain</td>
          <td class="text-center"><span class="cross" aria-label="Not included">&#10007;</span></td>
          <td class="text-center col-highlight"><span class="tick" aria-label="Included">&#10003;</span></td>
          <td class="text-center"><span class="tick" aria-label="Included">&#10003;</span></td>
        </tr>
        <tr>
          <td>Priority support</td>
          <td class="text-center"><span class="cross" aria-label="Not included">&#10007;</span></td>
          <td class="text-center col-highlight"><span class="tick" aria-label="Included">&#10003;</span></td>
          <td class="text-center"><span class="tick" aria-label="Included">&#10003;</span></td>
        </tr>
        <tr>
          <td>SSO &amp; SAML</td>
          <td class="text-center"><span class="cross" aria-label="Not included">&#10007;</span></td>
          <td class="text-center col-highlight"><span class="cross" aria-label="Not included">&#10007;</span></td>
          <td class="text-center"><span class="tick" aria-label="Included">&#10003;</span></td>
        </tr>
        <tr>
          <td>SLA uptime guarantee</td>
          <td class="text-center">99.5%</td>
          <td class="text-center col-highlight">99.9%</td>
          <td class="text-center">99.99%</td>
        </tr>
      </tbody>
      <tfoot>
        <tr>
          <td></td>
          <td class="text-center"><a href="#" class="btn btn-outline-secondary btn-sm">Get started</a></td>
          <td class="text-center col-highlight"><a href="#" class="btn btn-primary btn-sm">Start free trial</a></td>
          <td class="text-center"><a href="#" class="btn btn-outline-dark btn-sm">Contact sales</a></td>
        </tr>
      </tfoot>
    </table>
  </div>
</div>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js"></script>
</body>
</html>

Live Examples

Simple Two-Column Feature List

A minimal table comparing two product editions with text values. No sticky column required because there are few columns and the table fits on most screens.

Example 1

Card-based Plan Comparison

Uses Bootstrap grid and card components instead of a table element, giving full control over per-column styling and making each plan a distinct card on desktop.

Example 2

Striped Scrollable Specification Table

A horizontally scrollable, striped table suited to comparing technical specifications such as hardware components where many narrow columns are needed.

Example 3

Canvas Framework Variants

The Canvas template extends Bootstrap 5 with 1,658+ component variants. Generate any of these using Canvas Builder:

  • Pricing comparison table with highlighted 'Most Popular' column — generated automatically by Canvas Builder from a pricing prompt
  • Three-tier SaaS feature matrix with tick and cross icons
  • Card-based plan comparison with per-column CTA buttons
  • Scrollable hardware specification table with sticky feature column
  • Dark-header comparison table with badge labels on premium tiers

Best Practices

Sticky first column on wide tables

Apply position: sticky; left: 0 to the first th and td in each row using a shared class, and set a solid background colour matching the page so cells do not bleed through when the table scrolls horizontally. Always add z-index: 1 to prevent the sticky cell from rendering beneath other cells.

Accessibility for tick and cross icons

Avoid relying solely on colour or decorative characters to convey availability. Add aria-label="Included" or aria-label="Not included" to each icon element so screen readers can interpret the value correctly. Consider supplementing icons with visually hidden text via Bootstrap's .visually-hidden class for maximum compatibility.

Highlighting a recommended column

Use Bootstrap's contextual colour utilities such as bg-primary-subtle on tbody cells and bg-primary on the thead cell to highlight a recommended plan. Pair this with a .badge inside the header cell to reinforce the recommendation visually without altering the table's semantic structure.

Responsive behaviour at small breakpoints

Wrap the table in a div with the .table-responsive class to enable horizontal scrolling on viewports narrower than the table's natural width. For card-based layouts, switch to Bootstrap's grid (col-12 col-md-4) so each plan stacks vertically on mobile and expands to side-by-side columns on medium and larger screens.

FAQ

Does Bootstrap 5 have an official comparison table component?
No. Bootstrap 5 does not ship a comparison table component. The pattern is assembled from standard Bootstrap primitives: the .table, .table-bordered, and .table-responsive utilities, badge and card components, and contextual colour classes. All class names in these examples are either official Bootstrap 5 utilities or custom classes defined in an inline style block.
How do I make the feature column sticky while the plan columns scroll?
Add position: sticky; left: 0 and a matching background-color to all cells in the first column — both th and td. Wrap this in a shared CSS class such as .comparison-table th:first-child, .comparison-table td:first-child to keep the markup clean. The parent container must use overflow-x: auto (or Bootstrap's .table-responsive) for sticky positioning to activate.
Should I use a table element or card-based columns for this layout?
Use a genuine table element when you are comparing structured data across a fixed set of features, because it gives screen readers the correct row and column context via scope attributes. Use card-based columns when you need highly variable layouts per plan — such as different feature lists or custom imagery per tier — where a rigid table grid would constrain design too much.
How do I indicate which plan is recommended without breaking accessibility?
Place a .badge element inside the column's th cell with text such as 'Most Popular'. Apply a distinct background utility like bg-primary to the header and bg-primary-subtle to the body cells. Avoid conveying the recommendation through colour alone; the badge text itself must carry the meaning so colour-blind users and screen reader users receive the same information.