03 / 21
All 21 in 21 Tailwind CSS Pricing Tables
- 01Tailwind CSS Pricing Table with Monthly / Annual Toggle
- 02Tailwind Pricing Table with Currency Switcher (USD, GBP, EUR, AUD)
- 03Tailwind CSS Pricing Comparison Table with Expandable Features
- 04Tailwind Dark Mode Pricing Cards with Light / Dark Toggle
- 05Tailwind Pricing Cards with Hover Scale Effect
- 06Tailwind "Most Popular" Pricing Card with Animated Border Beam
- 07Tailwind Pricing Cards with Animated Discount Badges
- 08Tailwind Pricing Table CTA Button Hover Animation
- 09Tailwind Pricing Cards with Color-Changing Hover Themes
- 10Tailwind CSS 3D Flip Pricing Cards
- 11Tailwind Pricing Slider Calculator for Per-Seat Pricing
- 12Tailwind Tabbed Pricing Table for Multiple Products
- 13Tailwind Pricing Cards with Usage Meters & Progress Bars
- 14Tailwind Bundle Pricing Calculator with Checkboxes
- 15Glassmorphism Pricing Cards in Tailwind CSS
- 16Tailwind Pricing Card with Animated Gradient Border on Hover
- 17Tailwind Pricing Cards with Corner Ribbon & Bookmark Banner
- 18Neumorphic Pricing Table in Tailwind CSS (Soft UI)
- 19Mobile Swipe Pricing Carousel with Tailwind Scroll Snap
- 20Responsive Tailwind Pricing Table that Stacks into an Accordion
- 21Tailwind Pricing Cards with Skeleton Loading Shimmer
Tailwind CSS Pricing Comparison Table with Expandable Features
Minimal-first pricing that conversion teams love: three clean cards and one “Compare all features” toggle that unfolds a real, screen-reader-friendly <table> beneath. The unfold is v4 arbitrary values — grid-rows-[0fr] to group-has-checked/p:grid-rows-[1fr] — so the matrix animates to its natural height with no measuring.
Complete Tailwind CSS landing page templates in HTML, React, Next.js and Vue · from $49
Cruip · Affiliate link
The code
<section class="tpt-03 group/p w-full min-h-svh grid place-items-center bg-tpt03-bg px-5 py-16 font-tpt03-sans text-tpt03-ink antialiased" aria-label="Pricing with expandable feature comparison table">
<div class="grid w-full max-w-4xl justify-items-center gap-7">
<h2 class="text-center text-[clamp(26px,3.8vw,40px)] font-bold tracking-[-0.03em] text-balance">Start free. Upgrade when it clicks.</h2>
<div class="grid w-full gap-4 sm:grid-cols-3">
<article class="flex flex-col items-center gap-1 rounded-2xl border border-tpt03-line bg-white p-7 text-center">
<h3 class="text-[13px] font-semibold tracking-[0.08em] text-tpt03-mut uppercase">Basic</h3>
<p class="text-[42px] font-bold tracking-[-0.035em]">$0</p>
<span class="mb-5 text-[13px] text-tpt03-mut">forever</span>
<a href="#" class="grid min-h-11 w-full place-items-center rounded-xl border-[1.5px] border-tpt03-line text-sm font-semibold text-tpt03-ink no-underline transition-colors hover:border-tpt03-acc focus-visible:outline-3 focus-visible:outline-offset-2 focus-visible:outline-tpt03-acc">Sign up</a>
</article>
<article class="flex flex-col items-center gap-1 rounded-2xl bg-white p-7 text-center shadow-[0_18px_40px_-26px_var(--color-tpt03-acc)] ring-2 ring-tpt03-acc">
<h3 class="text-[13px] font-semibold tracking-[0.08em] text-tpt03-acc-ink uppercase">Pro</h3>
<p class="text-[42px] font-bold tracking-[-0.035em]">$19</p>
<span class="mb-5 text-[13px] text-tpt03-mut">per user / month</span>
<a href="#" class="grid min-h-11 w-full place-items-center rounded-xl bg-tpt03-acc text-sm font-semibold text-white no-underline transition-colors hover:bg-tpt03-acc-ink focus-visible:outline-3 focus-visible:outline-offset-2 focus-visible:outline-tpt03-acc">Start 14-day trial</a>
</article>
<article class="flex flex-col items-center gap-1 rounded-2xl border border-tpt03-line bg-white p-7 text-center">
<h3 class="text-[13px] font-semibold tracking-[0.08em] text-tpt03-mut uppercase">Enterprise</h3>
<p class="text-[42px] font-bold tracking-[-0.035em]">Custom</p>
<span class="mb-5 text-[13px] text-tpt03-mut">annual contract</span>
<a href="#" class="grid min-h-11 w-full place-items-center rounded-xl border-[1.5px] border-tpt03-line text-sm font-semibold text-tpt03-ink no-underline transition-colors hover:border-tpt03-acc focus-visible:outline-3 focus-visible:outline-offset-2 focus-visible:outline-tpt03-acc">Talk to sales</a>
</article>
</div>
<input type="checkbox" id="tpt03-more" class="peer sr-only" aria-controls="tpt03-matrix">
<label for="tpt03-more" class="flex min-h-11 cursor-pointer items-center gap-2.5 rounded-full border-[1.5px] border-tpt03-acc/35 px-5 text-sm font-semibold text-tpt03-acc-ink transition-colors hover:bg-tpt03-acc/8 peer-focus-visible:outline-3 peer-focus-visible:outline-offset-2 peer-focus-visible:outline-tpt03-acc">
<span class="grid">
<span class="col-start-1 row-start-1 transition-opacity group-has-checked/p:opacity-0">Compare all features</span>
<span class="col-start-1 row-start-1 opacity-0 transition-opacity group-has-checked/p:opacity-100">Hide comparison</span>
</span>
<svg class="size-3.5 transition-transform duration-300 group-has-checked/p:rotate-180 motion-reduce:transition-none" viewBox="0 0 14 14" aria-hidden="true"><path d="M2 5l5 5 5-5" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"/></svg>
</label>
<div id="tpt03-matrix" class="invisible grid w-full grid-rows-[0fr] transition-[grid-template-rows,visibility] duration-500 ease-[cubic-bezier(.6,0,.2,1)] group-has-checked/p:visible group-has-checked/p:grid-rows-[1fr] motion-reduce:transition-none">
<div class="min-h-0 overflow-hidden">
<div class="overflow-x-auto rounded-2xl border border-tpt03-line bg-white">
<table class="w-full min-w-[520px] border-collapse text-left text-sm">
<caption class="sr-only">Feature comparison of Basic, Pro and Enterprise plans</caption>
<thead class="bg-tpt03-head text-[11.5px] tracking-[0.08em] text-tpt03-mut uppercase">
<tr><th scope="col" class="sticky left-0 bg-tpt03-head px-4 py-3 font-semibold">Feature</th><th scope="col" class="px-4 py-3 font-semibold">Basic</th><th scope="col" class="bg-tpt03-acc/10 px-4 py-3 font-semibold text-tpt03-acc-ink">Pro</th><th scope="col" class="px-4 py-3 font-semibold">Enterprise</th></tr>
</thead>
<tbody class="text-tpt03-body *:border-t *:border-tpt03-line">
<tr><th scope="row" class="sticky left-0 bg-white px-4 py-3 font-medium text-tpt03-ink">Projects</th><td class="px-4 py-3">3</td><td class="bg-tpt03-acc/6 px-4 py-3">Unlimited</td><td class="px-4 py-3">Unlimited</td></tr>
<tr><th scope="row" class="sticky left-0 bg-white px-4 py-3 font-medium text-tpt03-ink">Storage</th><td class="px-4 py-3">1 GB</td><td class="bg-tpt03-acc/6 px-4 py-3">100 GB</td><td class="px-4 py-3">Unlimited</td></tr>
<tr><th scope="row" class="sticky left-0 bg-white px-4 py-3 font-medium text-tpt03-ink">API access</th><td class="px-4 py-3 text-tpt03-mut"><span aria-hidden="true">—</span><span class="sr-only">Not included</span></td><td class="bg-tpt03-acc/6 px-4 py-3 font-bold text-tpt03-acc-ink"><span aria-hidden="true">✓</span><span class="sr-only">Included</span></td><td class="px-4 py-3 font-bold text-tpt03-acc-ink"><span aria-hidden="true">✓</span><span class="sr-only">Included</span></td></tr>
<tr><th scope="row" class="sticky left-0 bg-white px-4 py-3 font-medium text-tpt03-ink">SSO / SAML</th><td class="px-4 py-3 text-tpt03-mut"><span aria-hidden="true">—</span><span class="sr-only">Not included</span></td><td class="bg-tpt03-acc/6 px-4 py-3 text-tpt03-mut"><span aria-hidden="true">—</span><span class="sr-only">Not included</span></td><td class="px-4 py-3 font-bold text-tpt03-acc-ink"><span aria-hidden="true">✓</span><span class="sr-only">Included</span></td></tr>
<tr><th scope="row" class="sticky left-0 bg-white px-4 py-3 font-medium text-tpt03-ink">Audit log</th><td class="px-4 py-3 text-tpt03-mut"><span aria-hidden="true">—</span><span class="sr-only">Not included</span></td><td class="bg-tpt03-acc/6 px-4 py-3 font-bold text-tpt03-acc-ink"><span aria-hidden="true">✓</span><span class="sr-only">Included</span></td><td class="px-4 py-3 font-bold text-tpt03-acc-ink"><span aria-hidden="true">✓</span><span class="sr-only">Included</span></td></tr>
<tr><th scope="row" class="sticky left-0 bg-white px-4 py-3 font-medium text-tpt03-ink">Support SLA</th><td class="px-4 py-3">Community</td><td class="bg-tpt03-acc/6 px-4 py-3">24 h</td><td class="px-4 py-3">1 h</td></tr>
</tbody>
</table>
</div>
</div>
</div>
<p aria-hidden="true" class="rounded-full border border-tpt03-line bg-white px-3.5 py-2 font-tpt03-mono text-[11.5px] text-tpt03-mut">grid-rows-[0fr] → group-has-checked/p:grid-rows-[1fr]</p>
</div>
</section><section class="tpt-03 group/p w-full min-h-svh grid place-items-center bg-tpt03-bg px-5 py-16 font-tpt03-sans text-tpt03-ink antialiased" aria-label="Pricing with expandable feature comparison table">
<div class="grid w-full max-w-4xl justify-items-center gap-7">
<h2 class="text-center text-[clamp(26px,3.8vw,40px)] font-bold tracking-[-0.03em] text-balance">Start free. Upgrade when it clicks.</h2>
<div class="grid w-full gap-4 sm:grid-cols-3">
<article class="flex flex-col items-center gap-1 rounded-2xl border border-tpt03-line bg-white p-7 text-center">
<h3 class="text-[13px] font-semibold tracking-[0.08em] text-tpt03-mut uppercase">Basic</h3>
<p class="text-[42px] font-bold tracking-[-0.035em]">$0</p>
<span class="mb-5 text-[13px] text-tpt03-mut">forever</span>
<a href="#" class="grid min-h-11 w-full place-items-center rounded-xl border-[1.5px] border-tpt03-line text-sm font-semibold text-tpt03-ink no-underline transition-colors hover:border-tpt03-acc focus-visible:outline-3 focus-visible:outline-offset-2 focus-visible:outline-tpt03-acc">Sign up</a>
</article>
<article class="flex flex-col items-center gap-1 rounded-2xl bg-white p-7 text-center shadow-[0_18px_40px_-26px_var(--color-tpt03-acc)] ring-2 ring-tpt03-acc">
<h3 class="text-[13px] font-semibold tracking-[0.08em] text-tpt03-acc-ink uppercase">Pro</h3>
<p class="text-[42px] font-bold tracking-[-0.035em]">$19</p>
<span class="mb-5 text-[13px] text-tpt03-mut">per user / month</span>
<a href="#" class="grid min-h-11 w-full place-items-center rounded-xl bg-tpt03-acc text-sm font-semibold text-white no-underline transition-colors hover:bg-tpt03-acc-ink focus-visible:outline-3 focus-visible:outline-offset-2 focus-visible:outline-tpt03-acc">Start 14-day trial</a>
</article>
<article class="flex flex-col items-center gap-1 rounded-2xl border border-tpt03-line bg-white p-7 text-center">
<h3 class="text-[13px] font-semibold tracking-[0.08em] text-tpt03-mut uppercase">Enterprise</h3>
<p class="text-[42px] font-bold tracking-[-0.035em]">Custom</p>
<span class="mb-5 text-[13px] text-tpt03-mut">annual contract</span>
<a href="#" class="grid min-h-11 w-full place-items-center rounded-xl border-[1.5px] border-tpt03-line text-sm font-semibold text-tpt03-ink no-underline transition-colors hover:border-tpt03-acc focus-visible:outline-3 focus-visible:outline-offset-2 focus-visible:outline-tpt03-acc">Talk to sales</a>
</article>
</div>
<input type="checkbox" id="tpt03-more" class="peer sr-only" aria-controls="tpt03-matrix">
<label for="tpt03-more" class="flex min-h-11 cursor-pointer items-center gap-2.5 rounded-full border-[1.5px] border-tpt03-acc/35 px-5 text-sm font-semibold text-tpt03-acc-ink transition-colors hover:bg-tpt03-acc/8 peer-focus-visible:outline-3 peer-focus-visible:outline-offset-2 peer-focus-visible:outline-tpt03-acc">
<span class="grid">
<span class="col-start-1 row-start-1 transition-opacity group-has-checked/p:opacity-0">Compare all features</span>
<span class="col-start-1 row-start-1 opacity-0 transition-opacity group-has-checked/p:opacity-100">Hide comparison</span>
</span>
<svg class="size-3.5 transition-transform duration-300 group-has-checked/p:rotate-180 motion-reduce:transition-none" viewBox="0 0 14 14" aria-hidden="true"><path d="M2 5l5 5 5-5" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"/></svg>
</label>
<div id="tpt03-matrix" class="invisible grid w-full grid-rows-[0fr] transition-[grid-template-rows,visibility] duration-500 ease-[cubic-bezier(.6,0,.2,1)] group-has-checked/p:visible group-has-checked/p:grid-rows-[1fr] motion-reduce:transition-none">
<div class="min-h-0 overflow-hidden">
<div class="overflow-x-auto rounded-2xl border border-tpt03-line bg-white">
<table class="w-full min-w-[520px] border-collapse text-left text-sm">
<caption class="sr-only">Feature comparison of Basic, Pro and Enterprise plans</caption>
<thead class="bg-tpt03-head text-[11.5px] tracking-[0.08em] text-tpt03-mut uppercase">
<tr><th scope="col" class="sticky left-0 bg-tpt03-head px-4 py-3 font-semibold">Feature</th><th scope="col" class="px-4 py-3 font-semibold">Basic</th><th scope="col" class="bg-tpt03-acc/10 px-4 py-3 font-semibold text-tpt03-acc-ink">Pro</th><th scope="col" class="px-4 py-3 font-semibold">Enterprise</th></tr>
</thead>
<tbody class="text-tpt03-body *:border-t *:border-tpt03-line">
<tr><th scope="row" class="sticky left-0 bg-white px-4 py-3 font-medium text-tpt03-ink">Projects</th><td class="px-4 py-3">3</td><td class="bg-tpt03-acc/6 px-4 py-3">Unlimited</td><td class="px-4 py-3">Unlimited</td></tr>
<tr><th scope="row" class="sticky left-0 bg-white px-4 py-3 font-medium text-tpt03-ink">Storage</th><td class="px-4 py-3">1 GB</td><td class="bg-tpt03-acc/6 px-4 py-3">100 GB</td><td class="px-4 py-3">Unlimited</td></tr>
<tr><th scope="row" class="sticky left-0 bg-white px-4 py-3 font-medium text-tpt03-ink">API access</th><td class="px-4 py-3 text-tpt03-mut"><span aria-hidden="true">—</span><span class="sr-only">Not included</span></td><td class="bg-tpt03-acc/6 px-4 py-3 font-bold text-tpt03-acc-ink"><span aria-hidden="true">✓</span><span class="sr-only">Included</span></td><td class="px-4 py-3 font-bold text-tpt03-acc-ink"><span aria-hidden="true">✓</span><span class="sr-only">Included</span></td></tr>
<tr><th scope="row" class="sticky left-0 bg-white px-4 py-3 font-medium text-tpt03-ink">SSO / SAML</th><td class="px-4 py-3 text-tpt03-mut"><span aria-hidden="true">—</span><span class="sr-only">Not included</span></td><td class="bg-tpt03-acc/6 px-4 py-3 text-tpt03-mut"><span aria-hidden="true">—</span><span class="sr-only">Not included</span></td><td class="px-4 py-3 font-bold text-tpt03-acc-ink"><span aria-hidden="true">✓</span><span class="sr-only">Included</span></td></tr>
<tr><th scope="row" class="sticky left-0 bg-white px-4 py-3 font-medium text-tpt03-ink">Audit log</th><td class="px-4 py-3 text-tpt03-mut"><span aria-hidden="true">—</span><span class="sr-only">Not included</span></td><td class="bg-tpt03-acc/6 px-4 py-3 font-bold text-tpt03-acc-ink"><span aria-hidden="true">✓</span><span class="sr-only">Included</span></td><td class="px-4 py-3 font-bold text-tpt03-acc-ink"><span aria-hidden="true">✓</span><span class="sr-only">Included</span></td></tr>
<tr><th scope="row" class="sticky left-0 bg-white px-4 py-3 font-medium text-tpt03-ink">Support SLA</th><td class="px-4 py-3">Community</td><td class="bg-tpt03-acc/6 px-4 py-3">24 h</td><td class="px-4 py-3">1 h</td></tr>
</tbody>
</table>
</div>
</div>
</div>
<p aria-hidden="true" class="rounded-full border border-tpt03-line bg-white px-3.5 py-2 font-tpt03-mono text-[11.5px] text-tpt03-mut">grid-rows-[0fr] → group-has-checked/p:grid-rows-[1fr]</p>
</div>
</section>@import "tailwindcss";
@theme {
--color-tpt03-bg: #f8f8f4;
--color-tpt03-bg: oklch(0.978 0.006 110);
--color-tpt03-head: #f3f4ee;
--color-tpt03-head: oklch(0.962 0.008 115);
--color-tpt03-ink: #1b1f1c;
--color-tpt03-ink: oklch(0.23 0.01 150);
--color-tpt03-body: #414842;
--color-tpt03-body: oklch(0.4 0.012 150);
--color-tpt03-mut: #5f665f;
--color-tpt03-mut: oklch(0.5 0.012 150);
--color-tpt03-line: #e3e5de;
--color-tpt03-line: oklch(0.915 0.01 120);
--color-tpt03-acc: #1f9a5b;
--color-tpt03-acc: oklch(0.6 0.15 155);
--color-tpt03-acc-ink: #127140;
--color-tpt03-acc-ink: oklch(0.47 0.12 155);
--font-tpt03-sans: 'Instrument Sans', system-ui, sans-serif;
--font-tpt03-mono: 'JetBrains Mono', ui-monospace, monospace;
}
/* Root rule: the full-bleed contract, stated in CSS as well as in the markup's utilities. */
.tpt-03 {
width: 100%;
min-height: 100svh;
}@import "tailwindcss";
@theme {
--color-tpt03-bg: #f8f8f4;
--color-tpt03-bg: oklch(0.978 0.006 110);
--color-tpt03-head: #f3f4ee;
--color-tpt03-head: oklch(0.962 0.008 115);
--color-tpt03-ink: #1b1f1c;
--color-tpt03-ink: oklch(0.23 0.01 150);
--color-tpt03-body: #414842;
--color-tpt03-body: oklch(0.4 0.012 150);
--color-tpt03-mut: #5f665f;
--color-tpt03-mut: oklch(0.5 0.012 150);
--color-tpt03-line: #e3e5de;
--color-tpt03-line: oklch(0.915 0.01 120);
--color-tpt03-acc: #1f9a5b;
--color-tpt03-acc: oklch(0.6 0.15 155);
--color-tpt03-acc-ink: #127140;
--color-tpt03-acc-ink: oklch(0.47 0.12 155);
--font-tpt03-sans: 'Instrument Sans', system-ui, sans-serif;
--font-tpt03-mono: 'JetBrains Mono', ui-monospace, monospace;
}
/* Root rule: the full-bleed contract, stated in CSS as well as in the markup's utilities. */
.tpt-03 {
width: 100%;
min-height: 100svh;
}Setup — do this once per project
Skip this if your project already runs Tailwind v4.
<script src="https://cdn.jsdelivr.net/npm/@tailwindcss/browser@4"></script>
<script src="https://cdn.jsdelivr.net/npm/@tailwindcss/browser@4"></script>Compiles in the browser — perfect for a CodePen or a quick test, not for production.
npm install tailwindcss @tailwindcss/vite
npm install tailwindcss @tailwindcss/vite// vite.config.js ("type": "module" in package.json)
import { defineConfig } from 'vite'
import tailwindcss from '@tailwindcss/vite'
export default defineConfig({
plugins: [tailwindcss()],
})// vite.config.js ("type": "module" in package.json)
import { defineConfig } from 'vite'
import tailwindcss from '@tailwindcss/vite'
export default defineConfig({
plugins: [tailwindcss()],
})Any v4 setup works — Vite, PostCSS or the CLI. Nothing in this demo is bundler-specific.
@import "tailwindcss";
@theme {
--color-tpt03-bg: #f8f8f4;
--color-tpt03-bg: oklch(0.978 0.006 110);
--color-tpt03-head: #f3f4ee;
--color-tpt03-head: oklch(0.962 0.008 115);
--color-tpt03-ink: #1b1f1c;
--color-tpt03-ink: oklch(0.23 0.01 150);
--color-tpt03-body: #414842;
--color-tpt03-body: oklch(0.4 0.012 150);
--color-tpt03-mut: #5f665f;
--color-tpt03-mut: oklch(0.5 0.012 150);
--color-tpt03-line: #e3e5de;
--color-tpt03-line: oklch(0.915 0.01 120);
--color-tpt03-acc: #1f9a5b;
--color-tpt03-acc: oklch(0.6 0.15 155);
--color-tpt03-acc-ink: #127140;
--color-tpt03-acc-ink: oklch(0.47 0.12 155);
--font-tpt03-sans: 'Instrument Sans', system-ui, sans-serif;
--font-tpt03-mono: 'JetBrains Mono', ui-monospace, monospace;
}
/* Root rule: the full-bleed contract, stated in CSS as well as in the markup's utilities. */
.tpt-03 {
width: 100%;
min-height: 100svh;
}@import "tailwindcss";
@theme {
--color-tpt03-bg: #f8f8f4;
--color-tpt03-bg: oklch(0.978 0.006 110);
--color-tpt03-head: #f3f4ee;
--color-tpt03-head: oklch(0.962 0.008 115);
--color-tpt03-ink: #1b1f1c;
--color-tpt03-ink: oklch(0.23 0.01 150);
--color-tpt03-body: #414842;
--color-tpt03-body: oklch(0.4 0.012 150);
--color-tpt03-mut: #5f665f;
--color-tpt03-mut: oklch(0.5 0.012 150);
--color-tpt03-line: #e3e5de;
--color-tpt03-line: oklch(0.915 0.01 120);
--color-tpt03-acc: #1f9a5b;
--color-tpt03-acc: oklch(0.6 0.15 155);
--color-tpt03-acc-ink: #127140;
--color-tpt03-acc-ink: oklch(0.47 0.12 155);
--font-tpt03-sans: 'Instrument Sans', system-ui, sans-serif;
--font-tpt03-mono: 'JetBrains Mono', ui-monospace, monospace;
}
/* Root rule: the full-bleed contract, stated in CSS as well as in the markup's utilities. */
.tpt-03 {
width: 100%;
min-height: 100svh;
}<link rel="preconnect" href="https://fonts.googleapis.com"> <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin> <link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Instrument+Sans:wght@400..700&family=JetBrains+Mono:wght@400;500&display=swap">
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Instrument+Sans:wght@400..700&family=JetBrains+Mono:wght@400;500&display=swap">What changed in the port
Which parts became utilities, which stayed CSS, and why.
.prc-03:has(.prc-03__sr:checked) .prc-03__fold{grid-template-rows:1fr}becamegroup-has-checked/p:grid-rows-[1fr]on the fold itself.- The table's descendant rules (
th,td, borders) moved onto the cells; row borders use the*:border-tchild variant on<tbody>. - UI upgrade from the CSS original: the folded table is now
invisible(not just clipped), so screen readers no longer read a collapsed matrix; cells usesr-onlytext instead of the unreliablearia-labelon<td>; a<caption>names the table. - UI upgrade: the matrix scrolls horizontally on phones with a sticky feature column, the Pro column is highlighted top to bottom, and the green accent darkened for text use (
acc-ink, 5.9:1).
Here's a working CSS demo from CodeFronts. Use it as-is or adapt to your framework. All classes are scoped under a unique prefix so the code won't collide with your existing styles. MIT licensed.
Demo: Tailwind CSS Pricing Comparison Table with Expandable Features
Source: https://codefronts.com/components/tailwind-css-pricing-tables/tailwind-css-pricing-comparison-table-expandable/
Minimal-first pricing that conversion teams love: three clean cards and one “Compare all features” toggle that unfolds a real, screen-reader-friendly <table> beneath. The unfold is v4 arbitrary values — grid-rows-[0fr] to group-has-checked/p:grid-rows-[1fr] — so the matrix animates to its natural height with no measuring.
## HTML
```html
<section class="tpt-03 group/p w-full min-h-svh grid place-items-center bg-tpt03-bg px-5 py-16 font-tpt03-sans text-tpt03-ink antialiased" aria-label="Pricing with expandable feature comparison table">
<div class="grid w-full max-w-4xl justify-items-center gap-7">
<h2 class="text-center text-[clamp(26px,3.8vw,40px)] font-bold tracking-[-0.03em] text-balance">Start free. Upgrade when it clicks.</h2>
<div class="grid w-full gap-4 sm:grid-cols-3">
<article class="flex flex-col items-center gap-1 rounded-2xl border border-tpt03-line bg-white p-7 text-center">
<h3 class="text-[13px] font-semibold tracking-[0.08em] text-tpt03-mut uppercase">Basic</h3>
<p class="text-[42px] font-bold tracking-[-0.035em]">$0</p>
<span class="mb-5 text-[13px] text-tpt03-mut">forever</span>
<a href="#" class="grid min-h-11 w-full place-items-center rounded-xl border-[1.5px] border-tpt03-line text-sm font-semibold text-tpt03-ink no-underline transition-colors hover:border-tpt03-acc focus-visible:outline-3 focus-visible:outline-offset-2 focus-visible:outline-tpt03-acc">Sign up</a>
</article>
<article class="flex flex-col items-center gap-1 rounded-2xl bg-white p-7 text-center shadow-[0_18px_40px_-26px_var(--color-tpt03-acc)] ring-2 ring-tpt03-acc">
<h3 class="text-[13px] font-semibold tracking-[0.08em] text-tpt03-acc-ink uppercase">Pro</h3>
<p class="text-[42px] font-bold tracking-[-0.035em]">$19</p>
<span class="mb-5 text-[13px] text-tpt03-mut">per user / month</span>
<a href="#" class="grid min-h-11 w-full place-items-center rounded-xl bg-tpt03-acc text-sm font-semibold text-white no-underline transition-colors hover:bg-tpt03-acc-ink focus-visible:outline-3 focus-visible:outline-offset-2 focus-visible:outline-tpt03-acc">Start 14-day trial</a>
</article>
<article class="flex flex-col items-center gap-1 rounded-2xl border border-tpt03-line bg-white p-7 text-center">
<h3 class="text-[13px] font-semibold tracking-[0.08em] text-tpt03-mut uppercase">Enterprise</h3>
<p class="text-[42px] font-bold tracking-[-0.035em]">Custom</p>
<span class="mb-5 text-[13px] text-tpt03-mut">annual contract</span>
<a href="#" class="grid min-h-11 w-full place-items-center rounded-xl border-[1.5px] border-tpt03-line text-sm font-semibold text-tpt03-ink no-underline transition-colors hover:border-tpt03-acc focus-visible:outline-3 focus-visible:outline-offset-2 focus-visible:outline-tpt03-acc">Talk to sales</a>
</article>
</div>
<input type="checkbox" id="tpt03-more" class="peer sr-only" aria-controls="tpt03-matrix">
<label for="tpt03-more" class="flex min-h-11 cursor-pointer items-center gap-2.5 rounded-full border-[1.5px] border-tpt03-acc/35 px-5 text-sm font-semibold text-tpt03-acc-ink transition-colors hover:bg-tpt03-acc/8 peer-focus-visible:outline-3 peer-focus-visible:outline-offset-2 peer-focus-visible:outline-tpt03-acc">
<span class="grid">
<span class="col-start-1 row-start-1 transition-opacity group-has-checked/p:opacity-0">Compare all features</span>
<span class="col-start-1 row-start-1 opacity-0 transition-opacity group-has-checked/p:opacity-100">Hide comparison</span>
</span>
<svg class="size-3.5 transition-transform duration-300 group-has-checked/p:rotate-180 motion-reduce:transition-none" viewBox="0 0 14 14" aria-hidden="true"><path d="M2 5l5 5 5-5" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"/></svg>
</label>
<div id="tpt03-matrix" class="invisible grid w-full grid-rows-[0fr] transition-[grid-template-rows,visibility] duration-500 ease-[cubic-bezier(.6,0,.2,1)] group-has-checked/p:visible group-has-checked/p:grid-rows-[1fr] motion-reduce:transition-none">
<div class="min-h-0 overflow-hidden">
<div class="overflow-x-auto rounded-2xl border border-tpt03-line bg-white">
<table class="w-full min-w-[520px] border-collapse text-left text-sm">
<caption class="sr-only">Feature comparison of Basic, Pro and Enterprise plans</caption>
<thead class="bg-tpt03-head text-[11.5px] tracking-[0.08em] text-tpt03-mut uppercase">
<tr><th scope="col" class="sticky left-0 bg-tpt03-head px-4 py-3 font-semibold">Feature</th><th scope="col" class="px-4 py-3 font-semibold">Basic</th><th scope="col" class="bg-tpt03-acc/10 px-4 py-3 font-semibold text-tpt03-acc-ink">Pro</th><th scope="col" class="px-4 py-3 font-semibold">Enterprise</th></tr>
</thead>
<tbody class="text-tpt03-body *:border-t *:border-tpt03-line">
<tr><th scope="row" class="sticky left-0 bg-white px-4 py-3 font-medium text-tpt03-ink">Projects</th><td class="px-4 py-3">3</td><td class="bg-tpt03-acc/6 px-4 py-3">Unlimited</td><td class="px-4 py-3">Unlimited</td></tr>
<tr><th scope="row" class="sticky left-0 bg-white px-4 py-3 font-medium text-tpt03-ink">Storage</th><td class="px-4 py-3">1 GB</td><td class="bg-tpt03-acc/6 px-4 py-3">100 GB</td><td class="px-4 py-3">Unlimited</td></tr>
<tr><th scope="row" class="sticky left-0 bg-white px-4 py-3 font-medium text-tpt03-ink">API access</th><td class="px-4 py-3 text-tpt03-mut"><span aria-hidden="true">—</span><span class="sr-only">Not included</span></td><td class="bg-tpt03-acc/6 px-4 py-3 font-bold text-tpt03-acc-ink"><span aria-hidden="true">✓</span><span class="sr-only">Included</span></td><td class="px-4 py-3 font-bold text-tpt03-acc-ink"><span aria-hidden="true">✓</span><span class="sr-only">Included</span></td></tr>
<tr><th scope="row" class="sticky left-0 bg-white px-4 py-3 font-medium text-tpt03-ink">SSO / SAML</th><td class="px-4 py-3 text-tpt03-mut"><span aria-hidden="true">—</span><span class="sr-only">Not included</span></td><td class="bg-tpt03-acc/6 px-4 py-3 text-tpt03-mut"><span aria-hidden="true">—</span><span class="sr-only">Not included</span></td><td class="px-4 py-3 font-bold text-tpt03-acc-ink"><span aria-hidden="true">✓</span><span class="sr-only">Included</span></td></tr>
<tr><th scope="row" class="sticky left-0 bg-white px-4 py-3 font-medium text-tpt03-ink">Audit log</th><td class="px-4 py-3 text-tpt03-mut"><span aria-hidden="true">—</span><span class="sr-only">Not included</span></td><td class="bg-tpt03-acc/6 px-4 py-3 font-bold text-tpt03-acc-ink"><span aria-hidden="true">✓</span><span class="sr-only">Included</span></td><td class="px-4 py-3 font-bold text-tpt03-acc-ink"><span aria-hidden="true">✓</span><span class="sr-only">Included</span></td></tr>
<tr><th scope="row" class="sticky left-0 bg-white px-4 py-3 font-medium text-tpt03-ink">Support SLA</th><td class="px-4 py-3">Community</td><td class="bg-tpt03-acc/6 px-4 py-3">24 h</td><td class="px-4 py-3">1 h</td></tr>
</tbody>
</table>
</div>
</div>
</div>
<p aria-hidden="true" class="rounded-full border border-tpt03-line bg-white px-3.5 py-2 font-tpt03-mono text-[11.5px] text-tpt03-mut">grid-rows-[0fr] → group-has-checked/p:grid-rows-[1fr]</p>
</div>
</section>
```
## CSS
```css
@import "tailwindcss";
@theme {
--color-tpt03-bg: #f8f8f4;
--color-tpt03-bg: oklch(0.978 0.006 110);
--color-tpt03-head: #f3f4ee;
--color-tpt03-head: oklch(0.962 0.008 115);
--color-tpt03-ink: #1b1f1c;
--color-tpt03-ink: oklch(0.23 0.01 150);
--color-tpt03-body: #414842;
--color-tpt03-body: oklch(0.4 0.012 150);
--color-tpt03-mut: #5f665f;
--color-tpt03-mut: oklch(0.5 0.012 150);
--color-tpt03-line: #e3e5de;
--color-tpt03-line: oklch(0.915 0.01 120);
--color-tpt03-acc: #1f9a5b;
--color-tpt03-acc: oklch(0.6 0.15 155);
--color-tpt03-acc-ink: #127140;
--color-tpt03-acc-ink: oklch(0.47 0.12 155);
--font-tpt03-sans: 'Instrument Sans', system-ui, sans-serif;
--font-tpt03-mono: 'JetBrains Mono', ui-monospace, monospace;
}
/* Root rule: the full-bleed contract, stated in CSS as well as in the markup's utilities. */
.tpt-03 {
width: 100%;
min-height: 100svh;
}
```Here's a working CSS demo from CodeFronts. Use it as-is or adapt to your framework. All classes are scoped under a unique prefix so the code won't collide with your existing styles. MIT licensed.
Demo: Tailwind CSS Pricing Comparison Table with Expandable Features
Source: https://codefronts.com/components/tailwind-css-pricing-tables/tailwind-css-pricing-comparison-table-expandable/
Minimal-first pricing that conversion teams love: three clean cards and one “Compare all features” toggle that unfolds a real, screen-reader-friendly <table> beneath. The unfold is v4 arbitrary values — grid-rows-[0fr] to group-has-checked/p:grid-rows-[1fr] — so the matrix animates to its natural height with no measuring.
## HTML
```html
<section class="tpt-03 group/p w-full min-h-svh grid place-items-center bg-tpt03-bg px-5 py-16 font-tpt03-sans text-tpt03-ink antialiased" aria-label="Pricing with expandable feature comparison table">
<div class="grid w-full max-w-4xl justify-items-center gap-7">
<h2 class="text-center text-[clamp(26px,3.8vw,40px)] font-bold tracking-[-0.03em] text-balance">Start free. Upgrade when it clicks.</h2>
<div class="grid w-full gap-4 sm:grid-cols-3">
<article class="flex flex-col items-center gap-1 rounded-2xl border border-tpt03-line bg-white p-7 text-center">
<h3 class="text-[13px] font-semibold tracking-[0.08em] text-tpt03-mut uppercase">Basic</h3>
<p class="text-[42px] font-bold tracking-[-0.035em]">$0</p>
<span class="mb-5 text-[13px] text-tpt03-mut">forever</span>
<a href="#" class="grid min-h-11 w-full place-items-center rounded-xl border-[1.5px] border-tpt03-line text-sm font-semibold text-tpt03-ink no-underline transition-colors hover:border-tpt03-acc focus-visible:outline-3 focus-visible:outline-offset-2 focus-visible:outline-tpt03-acc">Sign up</a>
</article>
<article class="flex flex-col items-center gap-1 rounded-2xl bg-white p-7 text-center shadow-[0_18px_40px_-26px_var(--color-tpt03-acc)] ring-2 ring-tpt03-acc">
<h3 class="text-[13px] font-semibold tracking-[0.08em] text-tpt03-acc-ink uppercase">Pro</h3>
<p class="text-[42px] font-bold tracking-[-0.035em]">$19</p>
<span class="mb-5 text-[13px] text-tpt03-mut">per user / month</span>
<a href="#" class="grid min-h-11 w-full place-items-center rounded-xl bg-tpt03-acc text-sm font-semibold text-white no-underline transition-colors hover:bg-tpt03-acc-ink focus-visible:outline-3 focus-visible:outline-offset-2 focus-visible:outline-tpt03-acc">Start 14-day trial</a>
</article>
<article class="flex flex-col items-center gap-1 rounded-2xl border border-tpt03-line bg-white p-7 text-center">
<h3 class="text-[13px] font-semibold tracking-[0.08em] text-tpt03-mut uppercase">Enterprise</h3>
<p class="text-[42px] font-bold tracking-[-0.035em]">Custom</p>
<span class="mb-5 text-[13px] text-tpt03-mut">annual contract</span>
<a href="#" class="grid min-h-11 w-full place-items-center rounded-xl border-[1.5px] border-tpt03-line text-sm font-semibold text-tpt03-ink no-underline transition-colors hover:border-tpt03-acc focus-visible:outline-3 focus-visible:outline-offset-2 focus-visible:outline-tpt03-acc">Talk to sales</a>
</article>
</div>
<input type="checkbox" id="tpt03-more" class="peer sr-only" aria-controls="tpt03-matrix">
<label for="tpt03-more" class="flex min-h-11 cursor-pointer items-center gap-2.5 rounded-full border-[1.5px] border-tpt03-acc/35 px-5 text-sm font-semibold text-tpt03-acc-ink transition-colors hover:bg-tpt03-acc/8 peer-focus-visible:outline-3 peer-focus-visible:outline-offset-2 peer-focus-visible:outline-tpt03-acc">
<span class="grid">
<span class="col-start-1 row-start-1 transition-opacity group-has-checked/p:opacity-0">Compare all features</span>
<span class="col-start-1 row-start-1 opacity-0 transition-opacity group-has-checked/p:opacity-100">Hide comparison</span>
</span>
<svg class="size-3.5 transition-transform duration-300 group-has-checked/p:rotate-180 motion-reduce:transition-none" viewBox="0 0 14 14" aria-hidden="true"><path d="M2 5l5 5 5-5" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"/></svg>
</label>
<div id="tpt03-matrix" class="invisible grid w-full grid-rows-[0fr] transition-[grid-template-rows,visibility] duration-500 ease-[cubic-bezier(.6,0,.2,1)] group-has-checked/p:visible group-has-checked/p:grid-rows-[1fr] motion-reduce:transition-none">
<div class="min-h-0 overflow-hidden">
<div class="overflow-x-auto rounded-2xl border border-tpt03-line bg-white">
<table class="w-full min-w-[520px] border-collapse text-left text-sm">
<caption class="sr-only">Feature comparison of Basic, Pro and Enterprise plans</caption>
<thead class="bg-tpt03-head text-[11.5px] tracking-[0.08em] text-tpt03-mut uppercase">
<tr><th scope="col" class="sticky left-0 bg-tpt03-head px-4 py-3 font-semibold">Feature</th><th scope="col" class="px-4 py-3 font-semibold">Basic</th><th scope="col" class="bg-tpt03-acc/10 px-4 py-3 font-semibold text-tpt03-acc-ink">Pro</th><th scope="col" class="px-4 py-3 font-semibold">Enterprise</th></tr>
</thead>
<tbody class="text-tpt03-body *:border-t *:border-tpt03-line">
<tr><th scope="row" class="sticky left-0 bg-white px-4 py-3 font-medium text-tpt03-ink">Projects</th><td class="px-4 py-3">3</td><td class="bg-tpt03-acc/6 px-4 py-3">Unlimited</td><td class="px-4 py-3">Unlimited</td></tr>
<tr><th scope="row" class="sticky left-0 bg-white px-4 py-3 font-medium text-tpt03-ink">Storage</th><td class="px-4 py-3">1 GB</td><td class="bg-tpt03-acc/6 px-4 py-3">100 GB</td><td class="px-4 py-3">Unlimited</td></tr>
<tr><th scope="row" class="sticky left-0 bg-white px-4 py-3 font-medium text-tpt03-ink">API access</th><td class="px-4 py-3 text-tpt03-mut"><span aria-hidden="true">—</span><span class="sr-only">Not included</span></td><td class="bg-tpt03-acc/6 px-4 py-3 font-bold text-tpt03-acc-ink"><span aria-hidden="true">✓</span><span class="sr-only">Included</span></td><td class="px-4 py-3 font-bold text-tpt03-acc-ink"><span aria-hidden="true">✓</span><span class="sr-only">Included</span></td></tr>
<tr><th scope="row" class="sticky left-0 bg-white px-4 py-3 font-medium text-tpt03-ink">SSO / SAML</th><td class="px-4 py-3 text-tpt03-mut"><span aria-hidden="true">—</span><span class="sr-only">Not included</span></td><td class="bg-tpt03-acc/6 px-4 py-3 text-tpt03-mut"><span aria-hidden="true">—</span><span class="sr-only">Not included</span></td><td class="px-4 py-3 font-bold text-tpt03-acc-ink"><span aria-hidden="true">✓</span><span class="sr-only">Included</span></td></tr>
<tr><th scope="row" class="sticky left-0 bg-white px-4 py-3 font-medium text-tpt03-ink">Audit log</th><td class="px-4 py-3 text-tpt03-mut"><span aria-hidden="true">—</span><span class="sr-only">Not included</span></td><td class="bg-tpt03-acc/6 px-4 py-3 font-bold text-tpt03-acc-ink"><span aria-hidden="true">✓</span><span class="sr-only">Included</span></td><td class="px-4 py-3 font-bold text-tpt03-acc-ink"><span aria-hidden="true">✓</span><span class="sr-only">Included</span></td></tr>
<tr><th scope="row" class="sticky left-0 bg-white px-4 py-3 font-medium text-tpt03-ink">Support SLA</th><td class="px-4 py-3">Community</td><td class="bg-tpt03-acc/6 px-4 py-3">24 h</td><td class="px-4 py-3">1 h</td></tr>
</tbody>
</table>
</div>
</div>
</div>
<p aria-hidden="true" class="rounded-full border border-tpt03-line bg-white px-3.5 py-2 font-tpt03-mono text-[11.5px] text-tpt03-mut">grid-rows-[0fr] → group-has-checked/p:grid-rows-[1fr]</p>
</div>
</section>
```
## CSS
```css
@import "tailwindcss";
@theme {
--color-tpt03-bg: #f8f8f4;
--color-tpt03-bg: oklch(0.978 0.006 110);
--color-tpt03-head: #f3f4ee;
--color-tpt03-head: oklch(0.962 0.008 115);
--color-tpt03-ink: #1b1f1c;
--color-tpt03-ink: oklch(0.23 0.01 150);
--color-tpt03-body: #414842;
--color-tpt03-body: oklch(0.4 0.012 150);
--color-tpt03-mut: #5f665f;
--color-tpt03-mut: oklch(0.5 0.012 150);
--color-tpt03-line: #e3e5de;
--color-tpt03-line: oklch(0.915 0.01 120);
--color-tpt03-acc: #1f9a5b;
--color-tpt03-acc: oklch(0.6 0.15 155);
--color-tpt03-acc-ink: #127140;
--color-tpt03-acc-ink: oklch(0.47 0.12 155);
--font-tpt03-sans: 'Instrument Sans', system-ui, sans-serif;
--font-tpt03-mono: 'JetBrains Mono', ui-monospace, monospace;
}
/* Root rule: the full-bleed contract, stated in CSS as well as in the markup's utilities. */
.tpt-03 {
width: 100%;
min-height: 100svh;
}
```How this works
The fold is two utilities. The wrapper transitions grid-template-rows; the inner child has min-h-0 overflow-hidden, so a 0fr track clips it to nothing and a 1fr track releases it to full height:
<div class="grid grid-rows-[0fr] transition-[grid-template-rows,visibility]
duration-500 invisible group-has-checked/p:grid-rows-[1fr]
group-has-checked/p:visible">
<div class="min-h-0 overflow-hidden">…</div>
</div>Label text swaps in one cell. “Compare all features” and “Hide comparison” stack via col-start-1 row-start-1, so the pill never changes width mid-click.
Cells speak. A ✓ or — glyph is aria-hidden, followed by sr-only “Included” / “Not included” text — aria-label on a <td> is ignored by several screen readers.
Make it yours
- Add rows freely — the 0fr → 1fr fold needs no height values.
- Open by default: add
checkedto#tpt03-more. - Highlight a different column: move the
bg-tpt03-acc/6utility to its cells. - Swap the glyphs for SVG icons; keep the
sr-onlytext.
Gotchas — read before shipping
- The inner child needs both
min-h-0andoverflow-hidden, or the 0fr track can't shrink it. grid-template-rowsis a layout animation — fine for a one-off, user-triggered reveal; never loop it.- Put
visibilityin the transition list so the table stays painted while it folds shut.
Browser support
| Chrome | Safari | Firefox | Edge |
|---|---|---|---|
| 111+ | 16.4+ | 128+ | 111+ |
Animatable grid tracks: Chrome 107 / Safari 16 / Firefox 66. Tailwind v4's sheet sets the floor.