02 / 13
All 13 in 13 Tailwind CSS Tables
- 01Responsive Tailwind Table That Stacks into Cards on Mobile
- 02Tailwind CSS Pricing Comparison Table with Billing Toggle
- 03Tailwind Admin Dashboard Data Table with Sticky Header, Filter & Sort
- 04Dark Neon Crypto Price Table in Tailwind CSS
- 05Tailwind Shopping Cart Table with Quantity Stepper & Live Totals
- 06Glassmorphism Striped Table in Tailwind CSS
- 07Tailwind Table with Sticky First Column & Horizontal Scroll
- 08Minimal Editorial Table Design in Tailwind CSS
- 09Tailwind Checkbox Table with :has() Row States & Progress Bar
- 10Tailwind Weekly Class Schedule Timetable
- 11Nutrition Facts Label in Tailwind CSS
- 12Neumorphic Table Design in Tailwind CSS
- 13Tailwind Table with Frosted Glass Sticky Header
Tailwind CSS Pricing Comparison Table with Billing Toggle
A three-tier SaaS feature matrix with a lifted, glowing Pro column — upgraded with a working monthly / yearly billing toggle in zero JavaScript. Two radio inputs drive every price on the table through group-has-[#ttb02-yearly:checked]/pricing:, and feature rows are grouped under section headings so the matrix scans like Stripe's, not like a spreadsheet.
Mosaic by Cruip: a complete Tailwind admin dashboard template in HTML, React, Next.js and Vue · $69
Cruip · Mosaic by Cruip · Affiliate link
The code
<section class="ttb-02 grid-cols-1 group/pricing w-full min-h-svh grid place-items-center bg-ttb02-bg bg-[radial-gradient(70%_50%_at_60%_0%,var(--color-ttb02-glow),transparent_70%)] px-5 py-14 font-ttb02-sans text-ttb02-ink" aria-label="SaaS pricing comparison table demo">
<div class="w-full max-w-4xl">
<header class="mb-10 grid justify-items-center gap-4 text-center">
<span class="rounded-full border border-ttb02-pro/30 bg-ttb02-pro/10 px-3.5 py-1 font-ttb02-mono text-[11px] font-medium tracking-[0.18em] text-ttb02-pro-ink uppercase">Pricing</span>
<h2 class="text-[clamp(28px,4vw,40px)] leading-tight font-bold tracking-[-0.03em] text-balance">Choose your power level</h2>
<p class="max-w-md text-[15px] text-ttb02-mut text-pretty">Scale from indie hacker to enterprise without friction. Switch plans anytime.</p>
<fieldset class="mt-2 inline-flex rounded-full bg-white/6 p-1 ring-1 ring-white/10">
<legend class="sr-only">Billing period</legend>
<label class="flex min-h-11 cursor-pointer items-center rounded-full px-5 text-sm font-semibold text-ttb02-mut transition has-checked:bg-white has-checked:text-ttb02-bg has-focus-visible:outline-2 has-focus-visible:outline-offset-2 has-focus-visible:outline-ttb02-pro">
<input class="sr-only" type="radio" name="ttb02-billing" id="ttb02-monthly" checked>Monthly
</label>
<label class="flex min-h-11 cursor-pointer items-center gap-2 rounded-full px-5 text-sm font-semibold text-ttb02-mut transition has-checked:bg-white has-checked:text-ttb02-bg has-focus-visible:outline-2 has-focus-visible:outline-offset-2 has-focus-visible:outline-ttb02-pro">
<input class="sr-only" type="radio" name="ttb02-billing" id="ttb02-yearly">Yearly
<span class="rounded-full bg-emerald-400/15 px-2 py-0.5 text-[11px] font-bold text-emerald-300">−20%</span>
</label>
</fieldset>
</header>
<div class="relative overflow-x-auto pt-4">
<table class="w-full min-w-[640px] border-separate border-spacing-0 text-left text-sm">
<caption class="sr-only">Feature comparison of Basic, Pro and Enterprise plans</caption>
<colgroup><col class="w-[34%]"><col class="w-[22%]"><col class="w-[22%]"><col class="w-[22%]"></colgroup>
<thead>
<tr class="align-top">
<td></td>
<th scope="col" class="px-5 pt-6 pb-6">
<div class="text-base font-semibold text-ttb02-basic">Basic</div>
<div class="mt-2 flex items-baseline gap-1"><span class="text-[32px] font-bold tracking-tight tabular-nums"><span class="group-has-[#ttb02-yearly:checked]/pricing:hidden">$9</span><span class="hidden group-has-[#ttb02-yearly:checked]/pricing:inline">$7</span></span><span class="text-ttb02-mut">/mo</span></div>
<p class="mt-1 text-xs font-normal text-ttb02-mut"><span class="group-has-[#ttb02-yearly:checked]/pricing:hidden">Billed monthly</span><span class="hidden group-has-[#ttb02-yearly:checked]/pricing:inline">$84 billed yearly</span></p>
</th>
<th scope="col" class="relative rounded-t-2xl bg-linear-to-b from-ttb02-pro/20 to-ttb02-pro/6 px-5 pt-6 pb-6 shadow-[0_-12px_40px_-12px_var(--color-ttb02-pro)] ring-1 ring-ttb02-pro/50 ring-inset">
<span class="absolute -top-3 left-5 rounded-full bg-linear-to-r from-ttb02-pro to-ttb02-pro2 px-2.5 py-1 text-[10px] font-bold tracking-[0.14em] text-white uppercase shadow-[0_6px_20px_-4px_var(--color-ttb02-pro)]">Most popular</span>
<div class="text-base font-semibold text-ttb02-pro-ink">Pro</div>
<div class="mt-2 flex items-baseline gap-1"><span class="text-[32px] font-bold tracking-tight tabular-nums"><span class="group-has-[#ttb02-yearly:checked]/pricing:hidden">$29</span><span class="hidden group-has-[#ttb02-yearly:checked]/pricing:inline">$23</span></span><span class="text-ttb02-mut">/mo</span></div>
<p class="mt-1 text-xs font-normal text-ttb02-mut"><span class="group-has-[#ttb02-yearly:checked]/pricing:hidden">Billed monthly</span><span class="hidden group-has-[#ttb02-yearly:checked]/pricing:inline">$276 billed yearly</span></p>
</th>
<th scope="col" class="px-5 pt-6 pb-6">
<div class="text-base font-semibold text-ttb02-ent">Enterprise</div>
<div class="mt-2 text-[32px] font-bold tracking-tight">Custom</div>
<p class="mt-1 text-xs font-normal text-ttb02-mut">Volume pricing & SSO</p>
</th>
</tr>
</thead>
<tbody class="[&_td]:border-b [&_td]:border-ttb02-line [&_td]:px-5 [&_td]:py-3.5 [&_th]:border-b [&_th]:border-ttb02-line [&_td:nth-child(3)]:border-x [&_td:nth-child(3)]:border-x-ttb02-pro/30 [&_td:nth-child(3)]:bg-ttb02-pro/6 [&_tr:hover_td]:bg-white/[0.025] [&_tr:hover_td:nth-child(3)]:bg-ttb02-pro/10">
<tr><th scope="colgroup" colspan="4" class="px-5 pt-6 pb-2.5 text-left font-ttb02-mono text-[11px] font-medium tracking-[0.16em] text-ttb02-mut uppercase">Usage</th></tr>
<tr><th scope="row" class="px-5 py-3.5 font-medium text-ttb02-mut">AI requests / month</th><td class="tabular-nums">500</td><td class="font-semibold text-ttb02-pro-ink tabular-nums">10,000</td><td>Unlimited</td></tr>
<tr><th scope="row" class="px-5 py-3.5 font-medium text-ttb02-mut">Team seats</th><td>1</td><td class="font-semibold text-ttb02-pro-ink">Up to 10</td><td>Unlimited</td></tr>
<tr><th scope="row" class="px-5 py-3.5 font-medium text-ttb02-mut">Analytics dashboard</th><td>Basic</td><td class="font-semibold text-ttb02-pro-ink">Advanced</td><td>Custom</td></tr>
<tr><th scope="colgroup" colspan="4" class="px-5 pt-7 pb-2.5 text-left font-ttb02-mono text-[11px] font-medium tracking-[0.16em] text-ttb02-mut uppercase">Platform & support</th></tr>
<tr><th scope="row" class="px-5 py-3.5 font-medium text-ttb02-mut">Custom integrations</th><td><span aria-hidden="true" class="text-ttb02-dim">—</span><span class="sr-only">Not included</span></td><td><svg class="size-5 text-emerald-400" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.6" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M5 12.5l4.5 4.5L19 7.5"/></svg><span class="sr-only">Included</span></td><td><svg class="size-5 text-emerald-400" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.6" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M5 12.5l4.5 4.5L19 7.5"/></svg><span class="sr-only">Included</span></td></tr>
<tr><th scope="row" class="px-5 py-3.5 font-medium text-ttb02-mut">Priority support</th><td><span aria-hidden="true" class="text-ttb02-dim">—</span><span class="sr-only">Not included</span></td><td><svg class="size-5 text-emerald-400" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.6" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M5 12.5l4.5 4.5L19 7.5"/></svg><span class="sr-only">Included</span></td><td><svg class="size-5 text-emerald-400" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.6" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M5 12.5l4.5 4.5L19 7.5"/></svg><span class="sr-only">Included</span></td></tr>
<tr><th scope="row" class="px-5 py-3.5 font-medium text-ttb02-mut">SLA guarantee</th><td><span aria-hidden="true" class="text-ttb02-dim">—</span><span class="sr-only">Not included</span></td><td><span aria-hidden="true" class="text-ttb02-dim">—</span><span class="sr-only">Not included</span></td><td class="font-semibold text-emerald-300">99.99% uptime</td></tr>
<tr class="[&_td]:border-b-0 [&_td]:pt-6 [&_td]:pb-7 [&_td]:bg-transparent!">
<td></td>
<td><a href="#" class="flex min-h-11 items-center justify-center rounded-xl text-sm font-semibold text-ttb02-basic ring-1 ring-ttb02-basic/40 transition ring-inset hover:bg-ttb02-basic hover:text-white focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-ttb02-basic">Start free</a></td>
<td class="rounded-b-2xl border-b! border-ttb02-pro/30! bg-ttb02-pro/6!"><a href="#" class="flex min-h-11 items-center justify-center gap-1.5 rounded-xl bg-linear-to-r from-ttb02-pro to-ttb02-pro2 text-sm font-semibold text-white shadow-[0_8px_24px_-8px_var(--color-ttb02-pro)] transition hover:-translate-y-px hover:shadow-[0_12px_30px_-8px_var(--color-ttb02-pro)] focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-ttb02-pro2 motion-reduce:transition-none">Get Pro <span aria-hidden="true">→</span></a></td>
<td><a href="#" class="flex min-h-11 items-center justify-center rounded-xl text-sm font-semibold text-ttb02-ent ring-1 ring-ttb02-ent/40 transition ring-inset hover:bg-ttb02-ent hover:text-ttb02-bg focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-ttb02-ent">Contact sales</a></td>
</tr>
</tbody>
</table>
</div>
</div>
</section><section class="ttb-02 grid-cols-1 group/pricing w-full min-h-svh grid place-items-center bg-ttb02-bg bg-[radial-gradient(70%_50%_at_60%_0%,var(--color-ttb02-glow),transparent_70%)] px-5 py-14 font-ttb02-sans text-ttb02-ink" aria-label="SaaS pricing comparison table demo">
<div class="w-full max-w-4xl">
<header class="mb-10 grid justify-items-center gap-4 text-center">
<span class="rounded-full border border-ttb02-pro/30 bg-ttb02-pro/10 px-3.5 py-1 font-ttb02-mono text-[11px] font-medium tracking-[0.18em] text-ttb02-pro-ink uppercase">Pricing</span>
<h2 class="text-[clamp(28px,4vw,40px)] leading-tight font-bold tracking-[-0.03em] text-balance">Choose your power level</h2>
<p class="max-w-md text-[15px] text-ttb02-mut text-pretty">Scale from indie hacker to enterprise without friction. Switch plans anytime.</p>
<fieldset class="mt-2 inline-flex rounded-full bg-white/6 p-1 ring-1 ring-white/10">
<legend class="sr-only">Billing period</legend>
<label class="flex min-h-11 cursor-pointer items-center rounded-full px-5 text-sm font-semibold text-ttb02-mut transition has-checked:bg-white has-checked:text-ttb02-bg has-focus-visible:outline-2 has-focus-visible:outline-offset-2 has-focus-visible:outline-ttb02-pro">
<input class="sr-only" type="radio" name="ttb02-billing" id="ttb02-monthly" checked>Monthly
</label>
<label class="flex min-h-11 cursor-pointer items-center gap-2 rounded-full px-5 text-sm font-semibold text-ttb02-mut transition has-checked:bg-white has-checked:text-ttb02-bg has-focus-visible:outline-2 has-focus-visible:outline-offset-2 has-focus-visible:outline-ttb02-pro">
<input class="sr-only" type="radio" name="ttb02-billing" id="ttb02-yearly">Yearly
<span class="rounded-full bg-emerald-400/15 px-2 py-0.5 text-[11px] font-bold text-emerald-300">−20%</span>
</label>
</fieldset>
</header>
<div class="relative overflow-x-auto pt-4">
<table class="w-full min-w-[640px] border-separate border-spacing-0 text-left text-sm">
<caption class="sr-only">Feature comparison of Basic, Pro and Enterprise plans</caption>
<colgroup><col class="w-[34%]"><col class="w-[22%]"><col class="w-[22%]"><col class="w-[22%]"></colgroup>
<thead>
<tr class="align-top">
<td></td>
<th scope="col" class="px-5 pt-6 pb-6">
<div class="text-base font-semibold text-ttb02-basic">Basic</div>
<div class="mt-2 flex items-baseline gap-1"><span class="text-[32px] font-bold tracking-tight tabular-nums"><span class="group-has-[#ttb02-yearly:checked]/pricing:hidden">$9</span><span class="hidden group-has-[#ttb02-yearly:checked]/pricing:inline">$7</span></span><span class="text-ttb02-mut">/mo</span></div>
<p class="mt-1 text-xs font-normal text-ttb02-mut"><span class="group-has-[#ttb02-yearly:checked]/pricing:hidden">Billed monthly</span><span class="hidden group-has-[#ttb02-yearly:checked]/pricing:inline">$84 billed yearly</span></p>
</th>
<th scope="col" class="relative rounded-t-2xl bg-linear-to-b from-ttb02-pro/20 to-ttb02-pro/6 px-5 pt-6 pb-6 shadow-[0_-12px_40px_-12px_var(--color-ttb02-pro)] ring-1 ring-ttb02-pro/50 ring-inset">
<span class="absolute -top-3 left-5 rounded-full bg-linear-to-r from-ttb02-pro to-ttb02-pro2 px-2.5 py-1 text-[10px] font-bold tracking-[0.14em] text-white uppercase shadow-[0_6px_20px_-4px_var(--color-ttb02-pro)]">Most popular</span>
<div class="text-base font-semibold text-ttb02-pro-ink">Pro</div>
<div class="mt-2 flex items-baseline gap-1"><span class="text-[32px] font-bold tracking-tight tabular-nums"><span class="group-has-[#ttb02-yearly:checked]/pricing:hidden">$29</span><span class="hidden group-has-[#ttb02-yearly:checked]/pricing:inline">$23</span></span><span class="text-ttb02-mut">/mo</span></div>
<p class="mt-1 text-xs font-normal text-ttb02-mut"><span class="group-has-[#ttb02-yearly:checked]/pricing:hidden">Billed monthly</span><span class="hidden group-has-[#ttb02-yearly:checked]/pricing:inline">$276 billed yearly</span></p>
</th>
<th scope="col" class="px-5 pt-6 pb-6">
<div class="text-base font-semibold text-ttb02-ent">Enterprise</div>
<div class="mt-2 text-[32px] font-bold tracking-tight">Custom</div>
<p class="mt-1 text-xs font-normal text-ttb02-mut">Volume pricing & SSO</p>
</th>
</tr>
</thead>
<tbody class="[&_td]:border-b [&_td]:border-ttb02-line [&_td]:px-5 [&_td]:py-3.5 [&_th]:border-b [&_th]:border-ttb02-line [&_td:nth-child(3)]:border-x [&_td:nth-child(3)]:border-x-ttb02-pro/30 [&_td:nth-child(3)]:bg-ttb02-pro/6 [&_tr:hover_td]:bg-white/[0.025] [&_tr:hover_td:nth-child(3)]:bg-ttb02-pro/10">
<tr><th scope="colgroup" colspan="4" class="px-5 pt-6 pb-2.5 text-left font-ttb02-mono text-[11px] font-medium tracking-[0.16em] text-ttb02-mut uppercase">Usage</th></tr>
<tr><th scope="row" class="px-5 py-3.5 font-medium text-ttb02-mut">AI requests / month</th><td class="tabular-nums">500</td><td class="font-semibold text-ttb02-pro-ink tabular-nums">10,000</td><td>Unlimited</td></tr>
<tr><th scope="row" class="px-5 py-3.5 font-medium text-ttb02-mut">Team seats</th><td>1</td><td class="font-semibold text-ttb02-pro-ink">Up to 10</td><td>Unlimited</td></tr>
<tr><th scope="row" class="px-5 py-3.5 font-medium text-ttb02-mut">Analytics dashboard</th><td>Basic</td><td class="font-semibold text-ttb02-pro-ink">Advanced</td><td>Custom</td></tr>
<tr><th scope="colgroup" colspan="4" class="px-5 pt-7 pb-2.5 text-left font-ttb02-mono text-[11px] font-medium tracking-[0.16em] text-ttb02-mut uppercase">Platform & support</th></tr>
<tr><th scope="row" class="px-5 py-3.5 font-medium text-ttb02-mut">Custom integrations</th><td><span aria-hidden="true" class="text-ttb02-dim">—</span><span class="sr-only">Not included</span></td><td><svg class="size-5 text-emerald-400" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.6" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M5 12.5l4.5 4.5L19 7.5"/></svg><span class="sr-only">Included</span></td><td><svg class="size-5 text-emerald-400" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.6" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M5 12.5l4.5 4.5L19 7.5"/></svg><span class="sr-only">Included</span></td></tr>
<tr><th scope="row" class="px-5 py-3.5 font-medium text-ttb02-mut">Priority support</th><td><span aria-hidden="true" class="text-ttb02-dim">—</span><span class="sr-only">Not included</span></td><td><svg class="size-5 text-emerald-400" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.6" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M5 12.5l4.5 4.5L19 7.5"/></svg><span class="sr-only">Included</span></td><td><svg class="size-5 text-emerald-400" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.6" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M5 12.5l4.5 4.5L19 7.5"/></svg><span class="sr-only">Included</span></td></tr>
<tr><th scope="row" class="px-5 py-3.5 font-medium text-ttb02-mut">SLA guarantee</th><td><span aria-hidden="true" class="text-ttb02-dim">—</span><span class="sr-only">Not included</span></td><td><span aria-hidden="true" class="text-ttb02-dim">—</span><span class="sr-only">Not included</span></td><td class="font-semibold text-emerald-300">99.99% uptime</td></tr>
<tr class="[&_td]:border-b-0 [&_td]:pt-6 [&_td]:pb-7 [&_td]:bg-transparent!">
<td></td>
<td><a href="#" class="flex min-h-11 items-center justify-center rounded-xl text-sm font-semibold text-ttb02-basic ring-1 ring-ttb02-basic/40 transition ring-inset hover:bg-ttb02-basic hover:text-white focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-ttb02-basic">Start free</a></td>
<td class="rounded-b-2xl border-b! border-ttb02-pro/30! bg-ttb02-pro/6!"><a href="#" class="flex min-h-11 items-center justify-center gap-1.5 rounded-xl bg-linear-to-r from-ttb02-pro to-ttb02-pro2 text-sm font-semibold text-white shadow-[0_8px_24px_-8px_var(--color-ttb02-pro)] transition hover:-translate-y-px hover:shadow-[0_12px_30px_-8px_var(--color-ttb02-pro)] focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-ttb02-pro2 motion-reduce:transition-none">Get Pro <span aria-hidden="true">→</span></a></td>
<td><a href="#" class="flex min-h-11 items-center justify-center rounded-xl text-sm font-semibold text-ttb02-ent ring-1 ring-ttb02-ent/40 transition ring-inset hover:bg-ttb02-ent hover:text-ttb02-bg focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-ttb02-ent">Contact sales</a></td>
</tr>
</tbody>
</table>
</div>
</div>
</section>@import "tailwindcss";
@theme {
--color-ttb02-bg: #07070f;
--color-ttb02-bg: oklch(0.12 0.015 285);
--color-ttb02-glow: #2b1a4d;
--color-ttb02-glow: oklch(0.26 0.09 300 / 0.75);
--color-ttb02-line: #1f1f36;
--color-ttb02-line: oklch(0.25 0.035 285);
--color-ttb02-ink: #ececfb;
--color-ttb02-ink: oklch(0.94 0.015 285);
--color-ttb02-mut: #a1a1bd;
--color-ttb02-mut: oklch(0.73 0.03 285);
--color-ttb02-dim: #55556e;
--color-ttb02-dim: oklch(0.46 0.03 285);
--color-ttb02-pro: #a855f7;
--color-ttb02-pro: oklch(0.63 0.25 304);
--color-ttb02-pro-ink: #d4b2ff;
--color-ttb02-pro-ink: oklch(0.82 0.11 304);
--color-ttb02-pro2: #06b6d4;
--color-ttb02-pro2: oklch(0.72 0.13 215);
--color-ttb02-basic: #60a5fa;
--color-ttb02-basic: oklch(0.71 0.14 255);
--color-ttb02-ent: #f5b041;
--color-ttb02-ent: oklch(0.8 0.14 75);
--font-ttb02-sans: 'Geist', system-ui, sans-serif;
--font-ttb02-mono: 'Geist Mono', ui-monospace, monospace;
}
/* Root rule: the full-bleed contract, stated in CSS as well as in the markup's utilities, so the
stage is sized before the browser build compiles. */
.ttb-02 {
width: 100%;
min-height: 100svh;
}@import "tailwindcss";
@theme {
--color-ttb02-bg: #07070f;
--color-ttb02-bg: oklch(0.12 0.015 285);
--color-ttb02-glow: #2b1a4d;
--color-ttb02-glow: oklch(0.26 0.09 300 / 0.75);
--color-ttb02-line: #1f1f36;
--color-ttb02-line: oklch(0.25 0.035 285);
--color-ttb02-ink: #ececfb;
--color-ttb02-ink: oklch(0.94 0.015 285);
--color-ttb02-mut: #a1a1bd;
--color-ttb02-mut: oklch(0.73 0.03 285);
--color-ttb02-dim: #55556e;
--color-ttb02-dim: oklch(0.46 0.03 285);
--color-ttb02-pro: #a855f7;
--color-ttb02-pro: oklch(0.63 0.25 304);
--color-ttb02-pro-ink: #d4b2ff;
--color-ttb02-pro-ink: oklch(0.82 0.11 304);
--color-ttb02-pro2: #06b6d4;
--color-ttb02-pro2: oklch(0.72 0.13 215);
--color-ttb02-basic: #60a5fa;
--color-ttb02-basic: oklch(0.71 0.14 255);
--color-ttb02-ent: #f5b041;
--color-ttb02-ent: oklch(0.8 0.14 75);
--font-ttb02-sans: 'Geist', system-ui, sans-serif;
--font-ttb02-mono: 'Geist Mono', ui-monospace, monospace;
}
/* Root rule: the full-bleed contract, stated in CSS as well as in the markup's utilities, so the
stage is sized before the browser build compiles. */
.ttb-02 {
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-ttb02-bg: #07070f;
--color-ttb02-bg: oklch(0.12 0.015 285);
--color-ttb02-glow: #2b1a4d;
--color-ttb02-glow: oklch(0.26 0.09 300 / 0.75);
--color-ttb02-line: #1f1f36;
--color-ttb02-line: oklch(0.25 0.035 285);
--color-ttb02-ink: #ececfb;
--color-ttb02-ink: oklch(0.94 0.015 285);
--color-ttb02-mut: #a1a1bd;
--color-ttb02-mut: oklch(0.73 0.03 285);
--color-ttb02-dim: #55556e;
--color-ttb02-dim: oklch(0.46 0.03 285);
--color-ttb02-pro: #a855f7;
--color-ttb02-pro: oklch(0.63 0.25 304);
--color-ttb02-pro-ink: #d4b2ff;
--color-ttb02-pro-ink: oklch(0.82 0.11 304);
--color-ttb02-pro2: #06b6d4;
--color-ttb02-pro2: oklch(0.72 0.13 215);
--color-ttb02-basic: #60a5fa;
--color-ttb02-basic: oklch(0.71 0.14 255);
--color-ttb02-ent: #f5b041;
--color-ttb02-ent: oklch(0.8 0.14 75);
--font-ttb02-sans: 'Geist', system-ui, sans-serif;
--font-ttb02-mono: 'Geist Mono', ui-monospace, monospace;
}
/* Root rule: the full-bleed contract, stated in CSS as well as in the markup's utilities, so the
stage is sized before the browser build compiles. */
.ttb-02 {
width: 100%;
min-height: 100svh;
}@import "tailwindcss";
@theme {
--color-ttb02-bg: #07070f;
--color-ttb02-bg: oklch(0.12 0.015 285);
--color-ttb02-glow: #2b1a4d;
--color-ttb02-glow: oklch(0.26 0.09 300 / 0.75);
--color-ttb02-line: #1f1f36;
--color-ttb02-line: oklch(0.25 0.035 285);
--color-ttb02-ink: #ececfb;
--color-ttb02-ink: oklch(0.94 0.015 285);
--color-ttb02-mut: #a1a1bd;
--color-ttb02-mut: oklch(0.73 0.03 285);
--color-ttb02-dim: #55556e;
--color-ttb02-dim: oklch(0.46 0.03 285);
--color-ttb02-pro: #a855f7;
--color-ttb02-pro: oklch(0.63 0.25 304);
--color-ttb02-pro-ink: #d4b2ff;
--color-ttb02-pro-ink: oklch(0.82 0.11 304);
--color-ttb02-pro2: #06b6d4;
--color-ttb02-pro2: oklch(0.72 0.13 215);
--color-ttb02-basic: #60a5fa;
--color-ttb02-basic: oklch(0.71 0.14 255);
--color-ttb02-ent: #f5b041;
--color-ttb02-ent: oklch(0.8 0.14 75);
--font-ttb02-sans: 'Geist', system-ui, sans-serif;
--font-ttb02-mono: 'Geist Mono', ui-monospace, monospace;
}
/* Root rule: the full-bleed contract, stated in CSS as well as in the markup's utilities, so the
stage is sized before the browser build compiles. */
.ttb-02 {
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=Geist:wght@400..800&family=Geist+Mono:wght@400..600&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=Geist:wght@400..800&family=Geist+Mono:wght@400..600&display=swap">What changed in the port
Which parts became utilities, which stayed CSS, and why.
<col class="pro">background plus thetbody td:nth-child(3)override collapsed into one honest rule:[&_td:nth-child(3)]:bg-ttb02-pro/6ontbody(column backgrounds lose to cell backgrounds anyway).- The
ct-02-shimmerbox-shadow pulse was dropped: a staticshadow-[0_6px_20px_-4px_…]glow reads as premium without pulling the eye from the prices. - UI upgrade from the CSS original: a working monthly / yearly toggle in pure CSS (
group-has-[#ttb02-yearly:checked]/pricing:), and feature rows grouped under Usage and Platform & support section headings withscope="colgroup". - UI upgrade: ✓ / ✕ glyphs became SVG checks and dashes with
sr-only"Included" / "Not included"; the barely-visible#374151cross (1.9:1) is now a dim dash that isn't mistaken for content; feature names are row headers; CTAs are 44px links.
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 Billing Toggle
Source: https://codefronts.com/snippets/tailwind-css-tables/tailwind-css-pricing-comparison-table-billing-toggle/
A three-tier SaaS feature matrix with a lifted, glowing Pro column — upgraded with a working monthly / yearly billing toggle in zero JavaScript. Two radio inputs drive every price on the table through group-has-[#ttb02-yearly:checked]/pricing:, and feature rows are grouped under section headings so the matrix scans like Stripe's, not like a spreadsheet.
## HTML
```html
<section class="ttb-02 grid-cols-1 group/pricing w-full min-h-svh grid place-items-center bg-ttb02-bg bg-[radial-gradient(70%_50%_at_60%_0%,var(--color-ttb02-glow),transparent_70%)] px-5 py-14 font-ttb02-sans text-ttb02-ink" aria-label="SaaS pricing comparison table demo">
<div class="w-full max-w-4xl">
<header class="mb-10 grid justify-items-center gap-4 text-center">
<span class="rounded-full border border-ttb02-pro/30 bg-ttb02-pro/10 px-3.5 py-1 font-ttb02-mono text-[11px] font-medium tracking-[0.18em] text-ttb02-pro-ink uppercase">Pricing</span>
<h2 class="text-[clamp(28px,4vw,40px)] leading-tight font-bold tracking-[-0.03em] text-balance">Choose your power level</h2>
<p class="max-w-md text-[15px] text-ttb02-mut text-pretty">Scale from indie hacker to enterprise without friction. Switch plans anytime.</p>
<fieldset class="mt-2 inline-flex rounded-full bg-white/6 p-1 ring-1 ring-white/10">
<legend class="sr-only">Billing period</legend>
<label class="flex min-h-11 cursor-pointer items-center rounded-full px-5 text-sm font-semibold text-ttb02-mut transition has-checked:bg-white has-checked:text-ttb02-bg has-focus-visible:outline-2 has-focus-visible:outline-offset-2 has-focus-visible:outline-ttb02-pro">
<input class="sr-only" type="radio" name="ttb02-billing" id="ttb02-monthly" checked>Monthly
</label>
<label class="flex min-h-11 cursor-pointer items-center gap-2 rounded-full px-5 text-sm font-semibold text-ttb02-mut transition has-checked:bg-white has-checked:text-ttb02-bg has-focus-visible:outline-2 has-focus-visible:outline-offset-2 has-focus-visible:outline-ttb02-pro">
<input class="sr-only" type="radio" name="ttb02-billing" id="ttb02-yearly">Yearly
<span class="rounded-full bg-emerald-400/15 px-2 py-0.5 text-[11px] font-bold text-emerald-300">−20%</span>
</label>
</fieldset>
</header>
<div class="relative overflow-x-auto pt-4">
<table class="w-full min-w-[640px] border-separate border-spacing-0 text-left text-sm">
<caption class="sr-only">Feature comparison of Basic, Pro and Enterprise plans</caption>
<colgroup><col class="w-[34%]"><col class="w-[22%]"><col class="w-[22%]"><col class="w-[22%]"></colgroup>
<thead>
<tr class="align-top">
<td></td>
<th scope="col" class="px-5 pt-6 pb-6">
<div class="text-base font-semibold text-ttb02-basic">Basic</div>
<div class="mt-2 flex items-baseline gap-1"><span class="text-[32px] font-bold tracking-tight tabular-nums"><span class="group-has-[#ttb02-yearly:checked]/pricing:hidden">$9</span><span class="hidden group-has-[#ttb02-yearly:checked]/pricing:inline">$7</span></span><span class="text-ttb02-mut">/mo</span></div>
<p class="mt-1 text-xs font-normal text-ttb02-mut"><span class="group-has-[#ttb02-yearly:checked]/pricing:hidden">Billed monthly</span><span class="hidden group-has-[#ttb02-yearly:checked]/pricing:inline">$84 billed yearly</span></p>
</th>
<th scope="col" class="relative rounded-t-2xl bg-linear-to-b from-ttb02-pro/20 to-ttb02-pro/6 px-5 pt-6 pb-6 shadow-[0_-12px_40px_-12px_var(--color-ttb02-pro)] ring-1 ring-ttb02-pro/50 ring-inset">
<span class="absolute -top-3 left-5 rounded-full bg-linear-to-r from-ttb02-pro to-ttb02-pro2 px-2.5 py-1 text-[10px] font-bold tracking-[0.14em] text-white uppercase shadow-[0_6px_20px_-4px_var(--color-ttb02-pro)]">Most popular</span>
<div class="text-base font-semibold text-ttb02-pro-ink">Pro</div>
<div class="mt-2 flex items-baseline gap-1"><span class="text-[32px] font-bold tracking-tight tabular-nums"><span class="group-has-[#ttb02-yearly:checked]/pricing:hidden">$29</span><span class="hidden group-has-[#ttb02-yearly:checked]/pricing:inline">$23</span></span><span class="text-ttb02-mut">/mo</span></div>
<p class="mt-1 text-xs font-normal text-ttb02-mut"><span class="group-has-[#ttb02-yearly:checked]/pricing:hidden">Billed monthly</span><span class="hidden group-has-[#ttb02-yearly:checked]/pricing:inline">$276 billed yearly</span></p>
</th>
<th scope="col" class="px-5 pt-6 pb-6">
<div class="text-base font-semibold text-ttb02-ent">Enterprise</div>
<div class="mt-2 text-[32px] font-bold tracking-tight">Custom</div>
<p class="mt-1 text-xs font-normal text-ttb02-mut">Volume pricing & SSO</p>
</th>
</tr>
</thead>
<tbody class="[&_td]:border-b [&_td]:border-ttb02-line [&_td]:px-5 [&_td]:py-3.5 [&_th]:border-b [&_th]:border-ttb02-line [&_td:nth-child(3)]:border-x [&_td:nth-child(3)]:border-x-ttb02-pro/30 [&_td:nth-child(3)]:bg-ttb02-pro/6 [&_tr:hover_td]:bg-white/[0.025] [&_tr:hover_td:nth-child(3)]:bg-ttb02-pro/10">
<tr><th scope="colgroup" colspan="4" class="px-5 pt-6 pb-2.5 text-left font-ttb02-mono text-[11px] font-medium tracking-[0.16em] text-ttb02-mut uppercase">Usage</th></tr>
<tr><th scope="row" class="px-5 py-3.5 font-medium text-ttb02-mut">AI requests / month</th><td class="tabular-nums">500</td><td class="font-semibold text-ttb02-pro-ink tabular-nums">10,000</td><td>Unlimited</td></tr>
<tr><th scope="row" class="px-5 py-3.5 font-medium text-ttb02-mut">Team seats</th><td>1</td><td class="font-semibold text-ttb02-pro-ink">Up to 10</td><td>Unlimited</td></tr>
<tr><th scope="row" class="px-5 py-3.5 font-medium text-ttb02-mut">Analytics dashboard</th><td>Basic</td><td class="font-semibold text-ttb02-pro-ink">Advanced</td><td>Custom</td></tr>
<tr><th scope="colgroup" colspan="4" class="px-5 pt-7 pb-2.5 text-left font-ttb02-mono text-[11px] font-medium tracking-[0.16em] text-ttb02-mut uppercase">Platform & support</th></tr>
<tr><th scope="row" class="px-5 py-3.5 font-medium text-ttb02-mut">Custom integrations</th><td><span aria-hidden="true" class="text-ttb02-dim">—</span><span class="sr-only">Not included</span></td><td><svg class="size-5 text-emerald-400" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.6" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M5 12.5l4.5 4.5L19 7.5"/></svg><span class="sr-only">Included</span></td><td><svg class="size-5 text-emerald-400" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.6" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M5 12.5l4.5 4.5L19 7.5"/></svg><span class="sr-only">Included</span></td></tr>
<tr><th scope="row" class="px-5 py-3.5 font-medium text-ttb02-mut">Priority support</th><td><span aria-hidden="true" class="text-ttb02-dim">—</span><span class="sr-only">Not included</span></td><td><svg class="size-5 text-emerald-400" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.6" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M5 12.5l4.5 4.5L19 7.5"/></svg><span class="sr-only">Included</span></td><td><svg class="size-5 text-emerald-400" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.6" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M5 12.5l4.5 4.5L19 7.5"/></svg><span class="sr-only">Included</span></td></tr>
<tr><th scope="row" class="px-5 py-3.5 font-medium text-ttb02-mut">SLA guarantee</th><td><span aria-hidden="true" class="text-ttb02-dim">—</span><span class="sr-only">Not included</span></td><td><span aria-hidden="true" class="text-ttb02-dim">—</span><span class="sr-only">Not included</span></td><td class="font-semibold text-emerald-300">99.99% uptime</td></tr>
<tr class="[&_td]:border-b-0 [&_td]:pt-6 [&_td]:pb-7 [&_td]:bg-transparent!">
<td></td>
<td><a href="#" class="flex min-h-11 items-center justify-center rounded-xl text-sm font-semibold text-ttb02-basic ring-1 ring-ttb02-basic/40 transition ring-inset hover:bg-ttb02-basic hover:text-white focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-ttb02-basic">Start free</a></td>
<td class="rounded-b-2xl border-b! border-ttb02-pro/30! bg-ttb02-pro/6!"><a href="#" class="flex min-h-11 items-center justify-center gap-1.5 rounded-xl bg-linear-to-r from-ttb02-pro to-ttb02-pro2 text-sm font-semibold text-white shadow-[0_8px_24px_-8px_var(--color-ttb02-pro)] transition hover:-translate-y-px hover:shadow-[0_12px_30px_-8px_var(--color-ttb02-pro)] focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-ttb02-pro2 motion-reduce:transition-none">Get Pro <span aria-hidden="true">→</span></a></td>
<td><a href="#" class="flex min-h-11 items-center justify-center rounded-xl text-sm font-semibold text-ttb02-ent ring-1 ring-ttb02-ent/40 transition ring-inset hover:bg-ttb02-ent hover:text-ttb02-bg focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-ttb02-ent">Contact sales</a></td>
</tr>
</tbody>
</table>
</div>
</div>
</section>
```
## CSS
```css
@import "tailwindcss";
@theme {
--color-ttb02-bg: #07070f;
--color-ttb02-bg: oklch(0.12 0.015 285);
--color-ttb02-glow: #2b1a4d;
--color-ttb02-glow: oklch(0.26 0.09 300 / 0.75);
--color-ttb02-line: #1f1f36;
--color-ttb02-line: oklch(0.25 0.035 285);
--color-ttb02-ink: #ececfb;
--color-ttb02-ink: oklch(0.94 0.015 285);
--color-ttb02-mut: #a1a1bd;
--color-ttb02-mut: oklch(0.73 0.03 285);
--color-ttb02-dim: #55556e;
--color-ttb02-dim: oklch(0.46 0.03 285);
--color-ttb02-pro: #a855f7;
--color-ttb02-pro: oklch(0.63 0.25 304);
--color-ttb02-pro-ink: #d4b2ff;
--color-ttb02-pro-ink: oklch(0.82 0.11 304);
--color-ttb02-pro2: #06b6d4;
--color-ttb02-pro2: oklch(0.72 0.13 215);
--color-ttb02-basic: #60a5fa;
--color-ttb02-basic: oklch(0.71 0.14 255);
--color-ttb02-ent: #f5b041;
--color-ttb02-ent: oklch(0.8 0.14 75);
--font-ttb02-sans: 'Geist', system-ui, sans-serif;
--font-ttb02-mono: 'Geist Mono', ui-monospace, monospace;
}
/* Root rule: the full-bleed contract, stated in CSS as well as in the markup's utilities, so the
stage is sized before the browser build compiles. */
.ttb-02 {
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 Billing Toggle
Source: https://codefronts.com/snippets/tailwind-css-tables/tailwind-css-pricing-comparison-table-billing-toggle/
A three-tier SaaS feature matrix with a lifted, glowing Pro column — upgraded with a working monthly / yearly billing toggle in zero JavaScript. Two radio inputs drive every price on the table through group-has-[#ttb02-yearly:checked]/pricing:, and feature rows are grouped under section headings so the matrix scans like Stripe's, not like a spreadsheet.
## HTML
```html
<section class="ttb-02 grid-cols-1 group/pricing w-full min-h-svh grid place-items-center bg-ttb02-bg bg-[radial-gradient(70%_50%_at_60%_0%,var(--color-ttb02-glow),transparent_70%)] px-5 py-14 font-ttb02-sans text-ttb02-ink" aria-label="SaaS pricing comparison table demo">
<div class="w-full max-w-4xl">
<header class="mb-10 grid justify-items-center gap-4 text-center">
<span class="rounded-full border border-ttb02-pro/30 bg-ttb02-pro/10 px-3.5 py-1 font-ttb02-mono text-[11px] font-medium tracking-[0.18em] text-ttb02-pro-ink uppercase">Pricing</span>
<h2 class="text-[clamp(28px,4vw,40px)] leading-tight font-bold tracking-[-0.03em] text-balance">Choose your power level</h2>
<p class="max-w-md text-[15px] text-ttb02-mut text-pretty">Scale from indie hacker to enterprise without friction. Switch plans anytime.</p>
<fieldset class="mt-2 inline-flex rounded-full bg-white/6 p-1 ring-1 ring-white/10">
<legend class="sr-only">Billing period</legend>
<label class="flex min-h-11 cursor-pointer items-center rounded-full px-5 text-sm font-semibold text-ttb02-mut transition has-checked:bg-white has-checked:text-ttb02-bg has-focus-visible:outline-2 has-focus-visible:outline-offset-2 has-focus-visible:outline-ttb02-pro">
<input class="sr-only" type="radio" name="ttb02-billing" id="ttb02-monthly" checked>Monthly
</label>
<label class="flex min-h-11 cursor-pointer items-center gap-2 rounded-full px-5 text-sm font-semibold text-ttb02-mut transition has-checked:bg-white has-checked:text-ttb02-bg has-focus-visible:outline-2 has-focus-visible:outline-offset-2 has-focus-visible:outline-ttb02-pro">
<input class="sr-only" type="radio" name="ttb02-billing" id="ttb02-yearly">Yearly
<span class="rounded-full bg-emerald-400/15 px-2 py-0.5 text-[11px] font-bold text-emerald-300">−20%</span>
</label>
</fieldset>
</header>
<div class="relative overflow-x-auto pt-4">
<table class="w-full min-w-[640px] border-separate border-spacing-0 text-left text-sm">
<caption class="sr-only">Feature comparison of Basic, Pro and Enterprise plans</caption>
<colgroup><col class="w-[34%]"><col class="w-[22%]"><col class="w-[22%]"><col class="w-[22%]"></colgroup>
<thead>
<tr class="align-top">
<td></td>
<th scope="col" class="px-5 pt-6 pb-6">
<div class="text-base font-semibold text-ttb02-basic">Basic</div>
<div class="mt-2 flex items-baseline gap-1"><span class="text-[32px] font-bold tracking-tight tabular-nums"><span class="group-has-[#ttb02-yearly:checked]/pricing:hidden">$9</span><span class="hidden group-has-[#ttb02-yearly:checked]/pricing:inline">$7</span></span><span class="text-ttb02-mut">/mo</span></div>
<p class="mt-1 text-xs font-normal text-ttb02-mut"><span class="group-has-[#ttb02-yearly:checked]/pricing:hidden">Billed monthly</span><span class="hidden group-has-[#ttb02-yearly:checked]/pricing:inline">$84 billed yearly</span></p>
</th>
<th scope="col" class="relative rounded-t-2xl bg-linear-to-b from-ttb02-pro/20 to-ttb02-pro/6 px-5 pt-6 pb-6 shadow-[0_-12px_40px_-12px_var(--color-ttb02-pro)] ring-1 ring-ttb02-pro/50 ring-inset">
<span class="absolute -top-3 left-5 rounded-full bg-linear-to-r from-ttb02-pro to-ttb02-pro2 px-2.5 py-1 text-[10px] font-bold tracking-[0.14em] text-white uppercase shadow-[0_6px_20px_-4px_var(--color-ttb02-pro)]">Most popular</span>
<div class="text-base font-semibold text-ttb02-pro-ink">Pro</div>
<div class="mt-2 flex items-baseline gap-1"><span class="text-[32px] font-bold tracking-tight tabular-nums"><span class="group-has-[#ttb02-yearly:checked]/pricing:hidden">$29</span><span class="hidden group-has-[#ttb02-yearly:checked]/pricing:inline">$23</span></span><span class="text-ttb02-mut">/mo</span></div>
<p class="mt-1 text-xs font-normal text-ttb02-mut"><span class="group-has-[#ttb02-yearly:checked]/pricing:hidden">Billed monthly</span><span class="hidden group-has-[#ttb02-yearly:checked]/pricing:inline">$276 billed yearly</span></p>
</th>
<th scope="col" class="px-5 pt-6 pb-6">
<div class="text-base font-semibold text-ttb02-ent">Enterprise</div>
<div class="mt-2 text-[32px] font-bold tracking-tight">Custom</div>
<p class="mt-1 text-xs font-normal text-ttb02-mut">Volume pricing & SSO</p>
</th>
</tr>
</thead>
<tbody class="[&_td]:border-b [&_td]:border-ttb02-line [&_td]:px-5 [&_td]:py-3.5 [&_th]:border-b [&_th]:border-ttb02-line [&_td:nth-child(3)]:border-x [&_td:nth-child(3)]:border-x-ttb02-pro/30 [&_td:nth-child(3)]:bg-ttb02-pro/6 [&_tr:hover_td]:bg-white/[0.025] [&_tr:hover_td:nth-child(3)]:bg-ttb02-pro/10">
<tr><th scope="colgroup" colspan="4" class="px-5 pt-6 pb-2.5 text-left font-ttb02-mono text-[11px] font-medium tracking-[0.16em] text-ttb02-mut uppercase">Usage</th></tr>
<tr><th scope="row" class="px-5 py-3.5 font-medium text-ttb02-mut">AI requests / month</th><td class="tabular-nums">500</td><td class="font-semibold text-ttb02-pro-ink tabular-nums">10,000</td><td>Unlimited</td></tr>
<tr><th scope="row" class="px-5 py-3.5 font-medium text-ttb02-mut">Team seats</th><td>1</td><td class="font-semibold text-ttb02-pro-ink">Up to 10</td><td>Unlimited</td></tr>
<tr><th scope="row" class="px-5 py-3.5 font-medium text-ttb02-mut">Analytics dashboard</th><td>Basic</td><td class="font-semibold text-ttb02-pro-ink">Advanced</td><td>Custom</td></tr>
<tr><th scope="colgroup" colspan="4" class="px-5 pt-7 pb-2.5 text-left font-ttb02-mono text-[11px] font-medium tracking-[0.16em] text-ttb02-mut uppercase">Platform & support</th></tr>
<tr><th scope="row" class="px-5 py-3.5 font-medium text-ttb02-mut">Custom integrations</th><td><span aria-hidden="true" class="text-ttb02-dim">—</span><span class="sr-only">Not included</span></td><td><svg class="size-5 text-emerald-400" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.6" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M5 12.5l4.5 4.5L19 7.5"/></svg><span class="sr-only">Included</span></td><td><svg class="size-5 text-emerald-400" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.6" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M5 12.5l4.5 4.5L19 7.5"/></svg><span class="sr-only">Included</span></td></tr>
<tr><th scope="row" class="px-5 py-3.5 font-medium text-ttb02-mut">Priority support</th><td><span aria-hidden="true" class="text-ttb02-dim">—</span><span class="sr-only">Not included</span></td><td><svg class="size-5 text-emerald-400" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.6" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M5 12.5l4.5 4.5L19 7.5"/></svg><span class="sr-only">Included</span></td><td><svg class="size-5 text-emerald-400" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.6" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M5 12.5l4.5 4.5L19 7.5"/></svg><span class="sr-only">Included</span></td></tr>
<tr><th scope="row" class="px-5 py-3.5 font-medium text-ttb02-mut">SLA guarantee</th><td><span aria-hidden="true" class="text-ttb02-dim">—</span><span class="sr-only">Not included</span></td><td><span aria-hidden="true" class="text-ttb02-dim">—</span><span class="sr-only">Not included</span></td><td class="font-semibold text-emerald-300">99.99% uptime</td></tr>
<tr class="[&_td]:border-b-0 [&_td]:pt-6 [&_td]:pb-7 [&_td]:bg-transparent!">
<td></td>
<td><a href="#" class="flex min-h-11 items-center justify-center rounded-xl text-sm font-semibold text-ttb02-basic ring-1 ring-ttb02-basic/40 transition ring-inset hover:bg-ttb02-basic hover:text-white focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-ttb02-basic">Start free</a></td>
<td class="rounded-b-2xl border-b! border-ttb02-pro/30! bg-ttb02-pro/6!"><a href="#" class="flex min-h-11 items-center justify-center gap-1.5 rounded-xl bg-linear-to-r from-ttb02-pro to-ttb02-pro2 text-sm font-semibold text-white shadow-[0_8px_24px_-8px_var(--color-ttb02-pro)] transition hover:-translate-y-px hover:shadow-[0_12px_30px_-8px_var(--color-ttb02-pro)] focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-ttb02-pro2 motion-reduce:transition-none">Get Pro <span aria-hidden="true">→</span></a></td>
<td><a href="#" class="flex min-h-11 items-center justify-center rounded-xl text-sm font-semibold text-ttb02-ent ring-1 ring-ttb02-ent/40 transition ring-inset hover:bg-ttb02-ent hover:text-ttb02-bg focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-ttb02-ent">Contact sales</a></td>
</tr>
</tbody>
</table>
</div>
</div>
</section>
```
## CSS
```css
@import "tailwindcss";
@theme {
--color-ttb02-bg: #07070f;
--color-ttb02-bg: oklch(0.12 0.015 285);
--color-ttb02-glow: #2b1a4d;
--color-ttb02-glow: oklch(0.26 0.09 300 / 0.75);
--color-ttb02-line: #1f1f36;
--color-ttb02-line: oklch(0.25 0.035 285);
--color-ttb02-ink: #ececfb;
--color-ttb02-ink: oklch(0.94 0.015 285);
--color-ttb02-mut: #a1a1bd;
--color-ttb02-mut: oklch(0.73 0.03 285);
--color-ttb02-dim: #55556e;
--color-ttb02-dim: oklch(0.46 0.03 285);
--color-ttb02-pro: #a855f7;
--color-ttb02-pro: oklch(0.63 0.25 304);
--color-ttb02-pro-ink: #d4b2ff;
--color-ttb02-pro-ink: oklch(0.82 0.11 304);
--color-ttb02-pro2: #06b6d4;
--color-ttb02-pro2: oklch(0.72 0.13 215);
--color-ttb02-basic: #60a5fa;
--color-ttb02-basic: oklch(0.71 0.14 255);
--color-ttb02-ent: #f5b041;
--color-ttb02-ent: oklch(0.8 0.14 75);
--font-ttb02-sans: 'Geist', system-ui, sans-serif;
--font-ttb02-mono: 'Geist Mono', ui-monospace, monospace;
}
/* Root rule: the full-bleed contract, stated in CSS as well as in the markup's utilities, so the
stage is sized before the browser build compiles. */
.ttb-02 {
width: 100%;
min-height: 100svh;
}
```How this works
The toggle is two radios and a :has(). The section is group/pricing; each price pair is a monthly span and a yearly span:
<span class="group-has-[#ttb02-yearly:checked]/pricing:hidden">$29</span>
<span class="hidden group-has-[#ttb02-yearly:checked]/pricing:inline">$23</span>The radios are sr-only inside their labels, so they stay keyboard-operable (arrow keys switch plans) while the label paints the pill via has-checked: and the focus ring via has-focus-visible:.
The lifted column is three pieces: a tinted, ringed header cell with rounded-t-2xl, a tbody-level nth-child(3) tint with side borders, and a CTA cell with rounded-b-2xl. border-separate border-spacing-0 is required — rounded corners do not paint on collapsed borders.
Make it yours
- Feature a different plan: move the
ring/bg-ttb02-proheader classes to another<th>and changenth-child(3)to its index. - Change the discount: edit the yearly spans and the "Save 20%" chip — the toggle logic never changes.
- Re-theme:
--color-ttb02-proand--color-ttb02-pro2drive the badge, ring, highlights and CTA gradient. - Add a fourth tier: add a
<th>and a<td>per row; the section-heading rows usecolspan="4", bump to 5.
Gotchas — read before shipping
has-*variants need the input inside the group element — the radios live in the section's header for that reason.- Hidden prices use
hidden, so screen readers only hear the active price; announce the switch with the visible "Billed yearly" note. - Safari clips
box-shadowon separate-border tables differently from Chrome; the Pro glow lives on the header cell'sringfor consistency.
Browser support
| Chrome | Safari | Firefox | Edge |
|---|---|---|---|
| 111+ | 16.4+ | 128+ | 111+ |
:has() is Chrome 105 / Safari 15.4 / Firefox 121 — without it the table shows monthly prices and the toggle simply does nothing.