Open demo

CSS code

HTML
<h2 class="cmp-title" id="cmp-title">Compare plans</h2>
<p class="cmp-sub">Feature comparison with a highlighted recommended column.</p>
<div class="cmp-card" role="region" tabindex="0" aria-label="Compare plans, scrollable">
<table class="cmp" aria-labelledby="cmp-title">
  <thead><tr>
    <td></td>
    <th scope="col"><span class="cmp-plan">Basic</span><span class="cmp-price">$0/mo</span></th>
    <th scope="col" class="hot"><span class="cmp-flag">Recommended</span><span class="cmp-plan">Pro</span><span class="cmp-price">$19/mo</span></th>
    <th scope="col"><span class="cmp-plan">Team</span><span class="cmp-price">$49/mo</span></th>
  </tr></thead>
  <tbody>
    <tr><th scope="row">Projects<span class="cmp-note">Active at once</span></th><td class="val">1</td><td class="hot val">Unlimited</td><td class="val">Unlimited</td></tr>
    <tr><th scope="row">Custom domain</th><td class="no"><span aria-hidden="true">—</span><span class="sr-only">Not included</span></td><td class="hot yes"><span aria-hidden="true">✓</span><span class="sr-only">Included</span></td><td class="yes"><span aria-hidden="true">✓</span><span class="sr-only">Included</span></td></tr>
    <tr><th scope="row">Analytics<span class="cmp-note">Retention window</span></th><td class="val">7 days</td><td class="hot val">1 year</td><td class="val">3 years</td></tr>
    <tr><th scope="row">Team seats</th><td class="no"><span aria-hidden="true">—</span><span class="sr-only">Not included</span></td><td class="hot no"><span aria-hidden="true">—</span><span class="sr-only">Not included</span></td><td class="yes"><span aria-hidden="true">✓</span><span class="sr-only">Included</span></td></tr>
    <tr><th scope="row">Priority support</th><td class="no"><span aria-hidden="true">—</span><span class="sr-only">Not included</span></td><td class="hot yes"><span aria-hidden="true">✓</span><span class="sr-only">Included</span></td><td class="yes"><span aria-hidden="true">✓</span><span class="sr-only">Included</span></td></tr>
    <tr><th scope="row">SSO / SAML</th><td class="no"><span aria-hidden="true">—</span><span class="sr-only">Not included</span></td><td class="hot no"><span aria-hidden="true">—</span><span class="sr-only">Not included</span></td><td class="yes"><span aria-hidden="true">✓</span><span class="sr-only">Included</span></td></tr>
  </tbody>
  <tfoot><tr>
    <td></td>
    <td><a class="cmp-btn" href="#">Start<span class="sr-only"> with Basic</span></a></td>
    <td class="hot"><a class="cmp-btn cmp-btn-primary" href="#">Go Pro</a></td>
    <td><a class="cmp-btn" href="#">Trial<span class="sr-only"> of the Team plan</span></a></td>
  </tr></tfoot>
</table>
</div>
CSS
/* Plan comparison table: row headers name the features, the recommended column is tinted and flagged,
   and ticks and dashes carry visually hidden text so screen readers hear "Included" / "Not included". */
.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}
.cmp-title{font-size:1.15rem;font-weight:700;letter-spacing:-.01em;text-align:center;margin:0 0 4px}
.cmp-sub{color:#5f6b85;font-size:.87rem;text-align:center;margin:0 0 22px}
.cmp-card{position:relative;overflow-x:auto;background:#fff;border:1px solid #e5e9f2;border-radius:16px;box-shadow:0 16px 36px -20px rgba(18,28,52,.2)}
.cmp-card:focus-visible{outline:2px solid #2563eb;outline-offset:2px}
.cmp{width:100%;border-collapse:separate;border-spacing:0;font-size:.88rem}
.cmp th,.cmp td{padding:13px 16px;text-align:center;border-bottom:1px solid #eef1f7}
.cmp tr:last-child>*{border-bottom:0}
.cmp thead th{font-size:.85rem;padding:18px 16px 14px}
.cmp-plan{display:block;font-weight:800;letter-spacing:-.01em}
.cmp-price{display:block;font-size:.75rem;font-weight:500;color:#636e88;margin-top:3px}
.cmp tbody th{text-align:left;font-weight:600;color:#33405c;font-size:.85rem}
.cmp-note{display:block;font-weight:400;font-size:.75rem;color:#636e88}
.cmp .hot{background:#f4f8ff;border-left:1px solid #dbe7ff;border-right:1px solid #dbe7ff}
.cmp thead .hot{position:relative;padding-top:32px}
.cmp-flag{position:absolute;top:0;left:0;right:0;background:#2563eb;color:#fff;font-size:.62rem;font-weight:800;letter-spacing:.08em;text-transform:uppercase;padding:4px}
.cmp .yes{color:#16803c;font-weight:800}
.cmp .no{color:#8590a3;font-weight:700}
.cmp .val{font-weight:600;color:#33405c}
.cmp tfoot td{padding:16px}
.cmp-btn{display:inline-block;white-space:nowrap;padding:9px 20px;border-radius:9px;font-size:.83rem;font-weight:700;text-decoration:none;border:1px solid #cdd6e6;color:#33405c;transition:background-color .15s}
.cmp-btn:hover{background:#f2f5fa}
.cmp-btn:focus-visible{outline:2px solid #2563eb;outline-offset:2px}
.cmp-btn-primary{background:#2563eb;border-color:#2563eb;color:#fff}
.cmp-btn-primary:hover{background:#1d4fd1}
@media (prefers-reduced-motion:reduce){.cmp-btn{transition:none}}

Bootstrap 5 code

Requires: Bootstrap 5.3.8 CSS

HTML
<h2 class="cmp-title text-center" id="cmp-title">Compare plans</h2>
<p class="cmp-sub text-center">Feature comparison with a highlighted recommended column.</p>
<div class="cmp-card table-responsive position-relative" role="region" tabindex="0" aria-label="Compare plans, scrollable">
<table class="table cmp align-middle mb-0" aria-labelledby="cmp-title">
  <thead><tr>
    <td></td>
    <th scope="col"><span class="cmp-plan">Basic</span><span class="cmp-price">$0/mo</span></th>
    <th scope="col" class="hot"><span class="cmp-flag">Recommended</span><span class="cmp-plan">Pro</span><span class="cmp-price">$19/mo</span></th>
    <th scope="col"><span class="cmp-plan">Team</span><span class="cmp-price">$49/mo</span></th>
  </tr></thead>
  <tbody>
    <tr><th scope="row">Projects<span class="cmp-note">Active at once</span></th><td class="val">1</td><td class="hot val">Unlimited</td><td class="val">Unlimited</td></tr>
    <tr><th scope="row">Custom domain</th><td class="no"><span aria-hidden="true">—</span><span class="visually-hidden">Not included</span></td><td class="hot yes"><span aria-hidden="true">✓</span><span class="visually-hidden">Included</span></td><td class="yes"><span aria-hidden="true">✓</span><span class="visually-hidden">Included</span></td></tr>
    <tr><th scope="row">Analytics<span class="cmp-note">Retention window</span></th><td class="val">7 days</td><td class="hot val">1 year</td><td class="val">3 years</td></tr>
    <tr><th scope="row">Team seats</th><td class="no"><span aria-hidden="true">—</span><span class="visually-hidden">Not included</span></td><td class="hot no"><span aria-hidden="true">—</span><span class="visually-hidden">Not included</span></td><td class="yes"><span aria-hidden="true">✓</span><span class="visually-hidden">Included</span></td></tr>
    <tr><th scope="row">Priority support</th><td class="no"><span aria-hidden="true">—</span><span class="visually-hidden">Not included</span></td><td class="hot yes"><span aria-hidden="true">✓</span><span class="visually-hidden">Included</span></td><td class="yes"><span aria-hidden="true">✓</span><span class="visually-hidden">Included</span></td></tr>
    <tr><th scope="row">SSO / SAML</th><td class="no"><span aria-hidden="true">—</span><span class="visually-hidden">Not included</span></td><td class="hot no"><span aria-hidden="true">—</span><span class="visually-hidden">Not included</span></td><td class="yes"><span aria-hidden="true">✓</span><span class="visually-hidden">Included</span></td></tr>
  </tbody>
  <tfoot><tr>
    <td></td>
    <td><a class="btn btn-outline-secondary" href="#">Start<span class="visually-hidden"> with Basic</span></a></td>
    <td class="hot"><a class="btn btn-primary" href="#">Go Pro</a></td>
    <td><a class="btn btn-outline-secondary" href="#">Trial<span class="visually-hidden"> of the Team plan</span></a></td>
  </tr></tfoot>
</table>
</div>
CSS
/* Bootstrap .table for a plan comparison: the recommended column is tinted through --bs-table-bg,
   the call-to-action links are .btn, and ticks and dashes carry .visually-hidden text. */
.cmp-title{font-size:1.15rem;font-weight:700;letter-spacing:-.01em;line-height:normal;margin:0 0 4px}
.cmp-sub{color:#5f6b85;font-size:.87rem;margin:0 0 22px}
.cmp-card{background:#fff;border:1px solid #e5e9f2;border-radius:16px;box-shadow:0 16px 36px -20px rgba(18,28,52,.2)}
.cmp-card:focus-visible{outline:2px solid #2563eb;outline-offset:2px}
.cmp{--bs-table-bg:#fff;--bs-table-color:#141c2e;--bs-table-border-color:#eef1f7;border-collapse:separate;border-spacing:0;font-size:.88rem}
.cmp>:not(caption)>*>*{padding:13px 16px;text-align:center}
.cmp>*>tr:last-child>*{border-bottom-width:0}
.cmp>thead{vertical-align:middle}
.cmp>thead>tr>*{font-size:.85rem;padding:18px 16px 14px}
.cmp-plan{display:block;font-weight:800;letter-spacing:-.01em}
.cmp-price{display:block;font-size:.75rem;font-weight:500;color:#636e88;margin-top:3px}
.cmp>tbody>tr>th{text-align:left;font-weight:600;font-size:.85rem;--bs-table-color:#33405c}
.cmp-note{display:block;font-weight:400;font-size:.75rem;color:#636e88}
.cmp .hot{--bs-table-bg:#f4f8ff;border-left:1px solid #dbe7ff;border-right:1px solid #dbe7ff}
.cmp>thead>tr>.hot{position:relative;padding-top:32px}
.cmp-flag{position:absolute;top:0;left:0;right:0;background:#2563eb;color:#fff;font-size:.62rem;font-weight:800;letter-spacing:.08em;text-transform:uppercase;padding:4px}
.cmp .yes{color:#16803c;font-weight:800}
.cmp .no{color:#8590a3;font-weight:700}
.cmp .val{font-weight:600;color:#33405c}
.cmp>tfoot>tr>td{padding:16px}
.cmp .btn{--bs-btn-padding-x:20px;--bs-btn-padding-y:9px;--bs-btn-font-size:.83rem;--bs-btn-font-weight:700;--bs-btn-line-height:normal;--bs-btn-border-radius:9px;white-space:nowrap;
  --bs-btn-focus-box-shadow:0 0 0 2px #fff,0 0 0 4px #2563eb}
.cmp .btn-outline-secondary{--bs-btn-color:#33405c;--bs-btn-border-color:#cdd6e6;--bs-btn-hover-color:#33405c;--bs-btn-hover-bg:#f2f5fa;--bs-btn-hover-border-color:#cdd6e6;
  --bs-btn-active-color:#33405c;--bs-btn-active-bg:#e8edf5;--bs-btn-active-border-color:#cdd6e6}
.cmp .btn-primary{--bs-btn-bg:#2563eb;--bs-btn-border-color:#2563eb;--bs-btn-hover-bg:#1d4fd1;--bs-btn-hover-border-color:#1d4fd1;--bs-btn-active-bg:#1a45b8;--bs-btn-active-border-color:#1a45b8}

Tailwind 4 code

Requires: Tailwind CSS 4

HTML
<h2 id="cmp-title" class="mb-1 text-center text-[1.15rem] font-bold tracking-[-.01em]">Compare plans</h2>
<p class="mb-[22px] text-center text-[.87rem] text-[#5f6b85]">Feature comparison with a highlighted recommended column.</p>
<div role="region" tabindex="0" aria-label="Compare plans, scrollable" class="relative overflow-x-auto rounded-2xl border border-[#e5e9f2] bg-white shadow-[0_16px_36px_-20px_rgba(18,28,52,.2)] focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-[#2563eb]">
<table aria-labelledby="cmp-title" class="w-full border-separate border-spacing-0 text-center text-[.88rem] [&_td]:border-b [&_td]:border-b-[#eef1f7] [&_td]:px-4 [&_td]:py-[13px] [&_th]:border-b [&_th]:border-b-[#eef1f7] [&_th]:px-4 [&_th]:py-[13px] [&_tr:last-child>*]:border-b-0">
  <thead class="text-[.85rem] [&_th]:pt-[18px] [&_th]:pb-[14px]"><tr>
    <td></td>
    <th scope="col"><span class="block font-extrabold tracking-[-.01em]">Basic</span><span class="mt-[3px] block text-[.75rem] font-medium text-[#636e88]">$0/mo</span></th>
    <th scope="col" class="relative border-x border-[#dbe7ff] bg-[#f4f8ff] pt-8!"><span class="absolute inset-x-0 top-0 bg-[#2563eb] p-1 text-[.62rem] font-extrabold tracking-[.08em] text-white uppercase">Recommended</span><span class="block font-extrabold tracking-[-.01em]">Pro</span><span class="mt-[3px] block text-[.75rem] font-medium text-[#636e88]">$19/mo</span></th>
    <th scope="col"><span class="block font-extrabold tracking-[-.01em]">Team</span><span class="mt-[3px] block text-[.75rem] font-medium text-[#636e88]">$49/mo</span></th>
  </tr></thead>
  <tbody class="[&_th]:text-left [&_th]:text-[.85rem] [&_th]:font-semibold [&_th]:text-[#33405c]">
    <tr><th scope="row">Projects<span class="block text-[.75rem] font-normal text-[#636e88]">Active at once</span></th><td class="font-semibold text-[#33405c]">1</td><td class="border-x border-[#dbe7ff] bg-[#f4f8ff] font-semibold text-[#33405c]">Unlimited</td><td class="font-semibold text-[#33405c]">Unlimited</td></tr>
    <tr><th scope="row">Custom domain</th><td class="font-bold text-[#8590a3]"><span aria-hidden="true">—</span><span class="sr-only">Not included</span></td><td class="border-x border-[#dbe7ff] bg-[#f4f8ff] font-extrabold text-[#16803c]"><span aria-hidden="true">✓</span><span class="sr-only">Included</span></td><td class="font-extrabold text-[#16803c]"><span aria-hidden="true">✓</span><span class="sr-only">Included</span></td></tr>
    <tr><th scope="row">Analytics<span class="block text-[.75rem] font-normal text-[#636e88]">Retention window</span></th><td class="font-semibold text-[#33405c]">7 days</td><td class="border-x border-[#dbe7ff] bg-[#f4f8ff] font-semibold text-[#33405c]">1 year</td><td class="font-semibold text-[#33405c]">3 years</td></tr>
    <tr><th scope="row">Team seats</th><td class="font-bold text-[#8590a3]"><span aria-hidden="true">—</span><span class="sr-only">Not included</span></td><td class="border-x border-[#dbe7ff] bg-[#f4f8ff] font-bold text-[#8590a3]"><span aria-hidden="true">—</span><span class="sr-only">Not included</span></td><td class="font-extrabold text-[#16803c]"><span aria-hidden="true">✓</span><span class="sr-only">Included</span></td></tr>
    <tr><th scope="row">Priority support</th><td class="font-bold text-[#8590a3]"><span aria-hidden="true">—</span><span class="sr-only">Not included</span></td><td class="border-x border-[#dbe7ff] bg-[#f4f8ff] font-extrabold text-[#16803c]"><span aria-hidden="true">✓</span><span class="sr-only">Included</span></td><td class="font-extrabold text-[#16803c]"><span aria-hidden="true">✓</span><span class="sr-only">Included</span></td></tr>
    <tr><th scope="row">SSO / SAML</th><td class="font-bold text-[#8590a3]"><span aria-hidden="true">—</span><span class="sr-only">Not included</span></td><td class="border-x border-[#dbe7ff] bg-[#f4f8ff] font-bold text-[#8590a3]"><span aria-hidden="true">—</span><span class="sr-only">Not included</span></td><td class="font-extrabold text-[#16803c]"><span aria-hidden="true">✓</span><span class="sr-only">Included</span></td></tr>
  </tbody>
  <tfoot class="[&_td]:p-4!"><tr>
    <td></td>
    <td><a class="inline-block whitespace-nowrap rounded-[9px] border px-5 py-[9px] text-[.83rem] font-bold no-underline transition-colors duration-150 focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-[#2563eb] motion-reduce:transition-none border-[#cdd6e6] text-[#33405c] hover:bg-[#f2f5fa]" href="#">Start<span class="sr-only"> with Basic</span></a></td>
    <td class="border-x border-[#dbe7ff] bg-[#f4f8ff]"><a class="inline-block whitespace-nowrap rounded-[9px] border px-5 py-[9px] text-[.83rem] font-bold no-underline transition-colors duration-150 focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-[#2563eb] motion-reduce:transition-none border-[#2563eb] bg-[#2563eb] text-white hover:bg-[#1d4fd1]" href="#">Go Pro</a></td>
    <td><a class="inline-block whitespace-nowrap rounded-[9px] border px-5 py-[9px] text-[.83rem] font-bold no-underline transition-colors duration-150 focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-[#2563eb] motion-reduce:transition-none border-[#cdd6e6] text-[#33405c] hover:bg-[#f2f5fa]" href="#">Trial<span class="sr-only"> of the Team plan</span></a></td>
  </tr></tfoot>
</table>
</div>

About this set

A pricing comparison for three plans with the recommended one highlighted. Plan names and prices form the column headers, feature names are row headers with an optional grey note underneath, and the Pro column is tinted light blue with side borders and a blue Recommended strip across its header. Cells hold values such as 7 days or Unlimited, a green tick or a grey dash. The ticks and dashes are hidden from screen readers and replaced by visually hidden text, Included or Not included, so a screen reader reads each cell as words, not as symbol names. A footer row holds a call-to-action link per plan, and short labels like Start and Trial carry hidden text so each link has a unique name. Use it below pricing cards or on a dedicated compare page. The card is a focusable scroll region, so on a phone the table scrolls sideways instead of squeezing the columns. The Bootstrap version recolours .table with –bs-table-bg for the highlighted column and uses .btn-primary and .btn-outline-secondary for the links; the Tailwind version uses border-x and bg- utilities per cell.

What’s included

  • Highlighted recommended column with a header strip
  • Ticks and dashes backed by Included and Not included text
  • Feature names as row headers with optional notes
  • Unique link names for each plan's call to action
  • Scrollable card on narrow screens

Accessibility

The table is labelled by its heading, plan headers use scope="col" and features scope="row". Symbols are aria-hidden with visually hidden text in their place, and link text such as Trial is extended with hidden words so each name is unique. Links and the scroll region show a 2px blue focus outline, and hover transitions stop under prefers-reduced-motion.

Customise it

The highlight is .cmp .hot (#f4f8ff with #dbe7ff borders) and .cmp-flag (#2563eb); ticks and dashes are .yes and .no. In Bootstrap set --bs-table-bg on .hot and the --bs-btn-* variables; in Tailwind change the bg-[#f4f8ff] and border-[#dbe7ff] utilities.