04 / 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 Dark Mode Pricing Cards with Light / Dark Toggle
Theme-aware pricing, the v4 way: every utility reads an @theme token (bg-tpt04-surface, text-tpt04-mut…), so one CSS rule re-points the tokens and the whole component crossfades. No dark: class is duplicated on any element — the palette stays a palette, and the switch is a real role="switch".
Complete Tailwind CSS landing page templates in HTML, React, Next.js and Vue · from $49
Cruip · Affiliate link
The code
<section class="tpt-04 group/p w-full min-h-svh grid place-items-center bg-tpt04-bg px-5 py-16 font-tpt04-sans text-tpt04-ink antialiased transition-colors duration-500" aria-label="Theme-adaptive pricing cards">
<div class="grid w-full max-w-5xl gap-9">
<header class="flex flex-wrap items-center justify-between gap-5">
<h2 class="text-[clamp(26px,3.8vw,40px)] font-extrabold tracking-[-0.03em]">Looks right in any theme</h2>
<input type="checkbox" id="tpt04-theme" role="switch" class="peer sr-only" aria-label="Dark theme">
<label for="tpt04-theme" class="relative flex h-11 cursor-pointer items-center gap-1 rounded-full border border-tpt04-line bg-tpt04-surface p-1 transition-colors duration-500 peer-focus-visible:outline-3 peer-focus-visible:outline-offset-3 peer-focus-visible:outline-tpt04-acc">
<span aria-hidden="true" class="absolute top-1 left-1 size-9 rounded-full bg-tpt04-acc/20 transition-transform duration-300 ease-[cubic-bezier(.5,1.5,.4,1)] group-has-checked/p:translate-x-10"></span>
<svg aria-hidden="true" class="relative size-9 p-2 text-tpt04-acc-ink transition-opacity group-has-checked/p:opacity-45" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"><circle cx="12" cy="12" r="4"/><path d="M12 2v2M12 20v2M4.9 4.9l1.4 1.4M17.7 17.7l1.4 1.4M2 12h2M20 12h2M4.9 19.1l1.4-1.4M17.7 6.3l1.4-1.4"/></svg>
<svg aria-hidden="true" class="relative size-9 p-2 text-tpt04-acc-ink opacity-45 transition-opacity group-has-checked/p:opacity-100" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M20 14.5A8 8 0 0 1 9.5 4 8 8 0 1 0 20 14.5z"/></svg>
</label>
</header>
<div class="grid gap-5 md:grid-cols-3">
<article class="flex flex-col gap-4 rounded-[20px] border border-tpt04-line bg-tpt04-surface p-7 transition-colors duration-500">
<h3 class="text-[13px] font-bold tracking-[0.08em] text-tpt04-mut uppercase transition-colors duration-500">Solo</h3>
<p class="text-[44px] leading-none font-extrabold tracking-[-0.035em]">$8<small class="text-[15px] font-semibold tracking-normal text-tpt04-mut">/mo</small></p>
<ul class="grid flex-1 content-start gap-2.5 text-sm text-tpt04-body transition-colors duration-500 *:flex *:gap-2.5 *:before:font-bold *:before:text-tpt04-acc-ink *:before:content-['✓']"><li>1 workspace</li><li>Core blocks</li><li>7-day history</li></ul>
<a href="#" class="grid min-h-11 place-items-center rounded-xl border-[1.5px] border-tpt04-line text-sm font-bold text-tpt04-ink no-underline transition-colors duration-300 hover:border-tpt04-acc focus-visible:outline-3 focus-visible:outline-offset-2 focus-visible:outline-tpt04-acc">Choose Solo</a>
</article>
<article class="relative flex flex-col gap-4 rounded-[20px] bg-tpt04-surface p-7 ring-2 ring-tpt04-acc transition-colors duration-500">
<span class="absolute -top-3 left-6 rounded-full bg-tpt04-acc px-3 py-1 text-[10.5px] font-bold tracking-[0.08em] text-tpt04-on-acc uppercase transition-colors duration-500">Most popular</span>
<h3 class="text-[13px] font-bold tracking-[0.08em] text-tpt04-acc-ink uppercase transition-colors duration-500">Craft</h3>
<p class="text-[44px] leading-none font-extrabold tracking-[-0.035em]">$20<small class="text-[15px] font-semibold tracking-normal text-tpt04-mut">/mo</small></p>
<ul class="grid flex-1 content-start gap-2.5 text-sm text-tpt04-body transition-colors duration-500 *:flex *:gap-2.5 *:before:font-bold *:before:text-tpt04-acc-ink *:before:content-['✓']"><li>5 workspaces</li><li>All blocks</li><li>Unlimited version history</li></ul>
<a href="#" class="grid min-h-11 place-items-center rounded-xl bg-tpt04-acc text-sm font-bold text-tpt04-on-acc no-underline transition duration-300 hover:brightness-105 focus-visible:outline-3 focus-visible:outline-offset-2 focus-visible:outline-tpt04-acc">Choose Craft</a>
</article>
<article class="flex flex-col gap-4 rounded-[20px] border border-tpt04-line bg-tpt04-surface p-7 transition-colors duration-500">
<h3 class="text-[13px] font-bold tracking-[0.08em] text-tpt04-mut uppercase transition-colors duration-500">Studio</h3>
<p class="text-[44px] leading-none font-extrabold tracking-[-0.035em]">$45<small class="text-[15px] font-semibold tracking-normal text-tpt04-mut">/mo</small></p>
<ul class="grid flex-1 content-start gap-2.5 text-sm text-tpt04-body transition-colors duration-500 *:flex *:gap-2.5 *:before:font-bold *:before:text-tpt04-acc-ink *:before:content-['✓']"><li>Unlimited workspaces</li><li>Team roles</li><li>Priority support</li></ul>
<a href="#" class="grid min-h-11 place-items-center rounded-xl border-[1.5px] border-tpt04-line text-sm font-bold text-tpt04-ink no-underline transition-colors duration-300 hover:border-tpt04-acc focus-visible:outline-3 focus-visible:outline-offset-2 focus-visible:outline-tpt04-acc">Choose Studio</a>
</article>
</div>
<p aria-hidden="true" class="justify-self-center rounded-full border border-tpt04-line px-3.5 py-2 font-tpt04-mono text-[11.5px] text-tpt04-mut transition-colors duration-500">@theme tokens · one swap rule · transition-colors</p>
</div>
</section><section class="tpt-04 group/p w-full min-h-svh grid place-items-center bg-tpt04-bg px-5 py-16 font-tpt04-sans text-tpt04-ink antialiased transition-colors duration-500" aria-label="Theme-adaptive pricing cards">
<div class="grid w-full max-w-5xl gap-9">
<header class="flex flex-wrap items-center justify-between gap-5">
<h2 class="text-[clamp(26px,3.8vw,40px)] font-extrabold tracking-[-0.03em]">Looks right in any theme</h2>
<input type="checkbox" id="tpt04-theme" role="switch" class="peer sr-only" aria-label="Dark theme">
<label for="tpt04-theme" class="relative flex h-11 cursor-pointer items-center gap-1 rounded-full border border-tpt04-line bg-tpt04-surface p-1 transition-colors duration-500 peer-focus-visible:outline-3 peer-focus-visible:outline-offset-3 peer-focus-visible:outline-tpt04-acc">
<span aria-hidden="true" class="absolute top-1 left-1 size-9 rounded-full bg-tpt04-acc/20 transition-transform duration-300 ease-[cubic-bezier(.5,1.5,.4,1)] group-has-checked/p:translate-x-10"></span>
<svg aria-hidden="true" class="relative size-9 p-2 text-tpt04-acc-ink transition-opacity group-has-checked/p:opacity-45" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"><circle cx="12" cy="12" r="4"/><path d="M12 2v2M12 20v2M4.9 4.9l1.4 1.4M17.7 17.7l1.4 1.4M2 12h2M20 12h2M4.9 19.1l1.4-1.4M17.7 6.3l1.4-1.4"/></svg>
<svg aria-hidden="true" class="relative size-9 p-2 text-tpt04-acc-ink opacity-45 transition-opacity group-has-checked/p:opacity-100" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M20 14.5A8 8 0 0 1 9.5 4 8 8 0 1 0 20 14.5z"/></svg>
</label>
</header>
<div class="grid gap-5 md:grid-cols-3">
<article class="flex flex-col gap-4 rounded-[20px] border border-tpt04-line bg-tpt04-surface p-7 transition-colors duration-500">
<h3 class="text-[13px] font-bold tracking-[0.08em] text-tpt04-mut uppercase transition-colors duration-500">Solo</h3>
<p class="text-[44px] leading-none font-extrabold tracking-[-0.035em]">$8<small class="text-[15px] font-semibold tracking-normal text-tpt04-mut">/mo</small></p>
<ul class="grid flex-1 content-start gap-2.5 text-sm text-tpt04-body transition-colors duration-500 *:flex *:gap-2.5 *:before:font-bold *:before:text-tpt04-acc-ink *:before:content-['✓']"><li>1 workspace</li><li>Core blocks</li><li>7-day history</li></ul>
<a href="#" class="grid min-h-11 place-items-center rounded-xl border-[1.5px] border-tpt04-line text-sm font-bold text-tpt04-ink no-underline transition-colors duration-300 hover:border-tpt04-acc focus-visible:outline-3 focus-visible:outline-offset-2 focus-visible:outline-tpt04-acc">Choose Solo</a>
</article>
<article class="relative flex flex-col gap-4 rounded-[20px] bg-tpt04-surface p-7 ring-2 ring-tpt04-acc transition-colors duration-500">
<span class="absolute -top-3 left-6 rounded-full bg-tpt04-acc px-3 py-1 text-[10.5px] font-bold tracking-[0.08em] text-tpt04-on-acc uppercase transition-colors duration-500">Most popular</span>
<h3 class="text-[13px] font-bold tracking-[0.08em] text-tpt04-acc-ink uppercase transition-colors duration-500">Craft</h3>
<p class="text-[44px] leading-none font-extrabold tracking-[-0.035em]">$20<small class="text-[15px] font-semibold tracking-normal text-tpt04-mut">/mo</small></p>
<ul class="grid flex-1 content-start gap-2.5 text-sm text-tpt04-body transition-colors duration-500 *:flex *:gap-2.5 *:before:font-bold *:before:text-tpt04-acc-ink *:before:content-['✓']"><li>5 workspaces</li><li>All blocks</li><li>Unlimited version history</li></ul>
<a href="#" class="grid min-h-11 place-items-center rounded-xl bg-tpt04-acc text-sm font-bold text-tpt04-on-acc no-underline transition duration-300 hover:brightness-105 focus-visible:outline-3 focus-visible:outline-offset-2 focus-visible:outline-tpt04-acc">Choose Craft</a>
</article>
<article class="flex flex-col gap-4 rounded-[20px] border border-tpt04-line bg-tpt04-surface p-7 transition-colors duration-500">
<h3 class="text-[13px] font-bold tracking-[0.08em] text-tpt04-mut uppercase transition-colors duration-500">Studio</h3>
<p class="text-[44px] leading-none font-extrabold tracking-[-0.035em]">$45<small class="text-[15px] font-semibold tracking-normal text-tpt04-mut">/mo</small></p>
<ul class="grid flex-1 content-start gap-2.5 text-sm text-tpt04-body transition-colors duration-500 *:flex *:gap-2.5 *:before:font-bold *:before:text-tpt04-acc-ink *:before:content-['✓']"><li>Unlimited workspaces</li><li>Team roles</li><li>Priority support</li></ul>
<a href="#" class="grid min-h-11 place-items-center rounded-xl border-[1.5px] border-tpt04-line text-sm font-bold text-tpt04-ink no-underline transition-colors duration-300 hover:border-tpt04-acc focus-visible:outline-3 focus-visible:outline-offset-2 focus-visible:outline-tpt04-acc">Choose Studio</a>
</article>
</div>
<p aria-hidden="true" class="justify-self-center rounded-full border border-tpt04-line px-3.5 py-2 font-tpt04-mono text-[11.5px] text-tpt04-mut transition-colors duration-500">@theme tokens · one swap rule · transition-colors</p>
</div>
</section>@import "tailwindcss";
@theme {
--color-tpt04-bg: #f4f2ec;
--color-tpt04-bg: oklch(0.96 0.008 90);
--color-tpt04-surface: #ffffff;
--color-tpt04-surface: oklch(1 0 0);
--color-tpt04-line: #e2dfd5;
--color-tpt04-line: oklch(0.9 0.012 90);
--color-tpt04-ink: #211f1a;
--color-tpt04-ink: oklch(0.23 0.01 90);
--color-tpt04-body: #4a473f;
--color-tpt04-body: oklch(0.41 0.012 90);
--color-tpt04-mut: #6a665b;
--color-tpt04-mut: oklch(0.52 0.015 90);
--color-tpt04-acc: #d88a1e;
--color-tpt04-acc: oklch(0.7 0.15 65);
--color-tpt04-acc-ink: #9a5a00;
--color-tpt04-acc-ink: oklch(0.52 0.12 62);
--color-tpt04-on-acc: #1a1206;
--color-tpt04-on-acc: oklch(0.2 0.03 70);
--font-tpt04-sans: 'Bricolage Grotesque', system-ui, sans-serif;
--font-tpt04-mono: 'JetBrains Mono', ui-monospace, monospace;
}
/* Root rule: the full-bleed contract, stated in CSS as well as in the markup's utilities. */
.tpt-04 {
width: 100%;
min-height: 100svh;
}
/* The whole dark theme: re-point the tokens every utility already reads.
In production: [data-theme="dark"] .tpt-04 { … } */
.tpt-04:has(#tpt04-theme:checked) {
--color-tpt04-bg: #14130f;
--color-tpt04-bg: oklch(0.18 0.008 85);
--color-tpt04-surface: #1f1d17;
--color-tpt04-surface: oklch(0.225 0.01 85);
--color-tpt04-line: #36332a;
--color-tpt04-line: oklch(0.32 0.012 85);
--color-tpt04-ink: #f1eee3;
--color-tpt04-ink: oklch(0.95 0.012 90);
--color-tpt04-body: #cfcabb;
--color-tpt04-body: oklch(0.84 0.018 90);
--color-tpt04-mut: #a7a190;
--color-tpt04-mut: oklch(0.71 0.02 90);
--color-tpt04-acc: #f0b44a;
--color-tpt04-acc: oklch(0.8 0.14 75);
--color-tpt04-acc-ink: #f0b44a;
--color-tpt04-acc-ink: oklch(0.8 0.14 75);
}@import "tailwindcss";
@theme {
--color-tpt04-bg: #f4f2ec;
--color-tpt04-bg: oklch(0.96 0.008 90);
--color-tpt04-surface: #ffffff;
--color-tpt04-surface: oklch(1 0 0);
--color-tpt04-line: #e2dfd5;
--color-tpt04-line: oklch(0.9 0.012 90);
--color-tpt04-ink: #211f1a;
--color-tpt04-ink: oklch(0.23 0.01 90);
--color-tpt04-body: #4a473f;
--color-tpt04-body: oklch(0.41 0.012 90);
--color-tpt04-mut: #6a665b;
--color-tpt04-mut: oklch(0.52 0.015 90);
--color-tpt04-acc: #d88a1e;
--color-tpt04-acc: oklch(0.7 0.15 65);
--color-tpt04-acc-ink: #9a5a00;
--color-tpt04-acc-ink: oklch(0.52 0.12 62);
--color-tpt04-on-acc: #1a1206;
--color-tpt04-on-acc: oklch(0.2 0.03 70);
--font-tpt04-sans: 'Bricolage Grotesque', system-ui, sans-serif;
--font-tpt04-mono: 'JetBrains Mono', ui-monospace, monospace;
}
/* Root rule: the full-bleed contract, stated in CSS as well as in the markup's utilities. */
.tpt-04 {
width: 100%;
min-height: 100svh;
}
/* The whole dark theme: re-point the tokens every utility already reads.
In production: [data-theme="dark"] .tpt-04 { … } */
.tpt-04:has(#tpt04-theme:checked) {
--color-tpt04-bg: #14130f;
--color-tpt04-bg: oklch(0.18 0.008 85);
--color-tpt04-surface: #1f1d17;
--color-tpt04-surface: oklch(0.225 0.01 85);
--color-tpt04-line: #36332a;
--color-tpt04-line: oklch(0.32 0.012 85);
--color-tpt04-ink: #f1eee3;
--color-tpt04-ink: oklch(0.95 0.012 90);
--color-tpt04-body: #cfcabb;
--color-tpt04-body: oklch(0.84 0.018 90);
--color-tpt04-mut: #a7a190;
--color-tpt04-mut: oklch(0.71 0.02 90);
--color-tpt04-acc: #f0b44a;
--color-tpt04-acc: oklch(0.8 0.14 75);
--color-tpt04-acc-ink: #f0b44a;
--color-tpt04-acc-ink: oklch(0.8 0.14 75);
}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-tpt04-bg: #f4f2ec;
--color-tpt04-bg: oklch(0.96 0.008 90);
--color-tpt04-surface: #ffffff;
--color-tpt04-surface: oklch(1 0 0);
--color-tpt04-line: #e2dfd5;
--color-tpt04-line: oklch(0.9 0.012 90);
--color-tpt04-ink: #211f1a;
--color-tpt04-ink: oklch(0.23 0.01 90);
--color-tpt04-body: #4a473f;
--color-tpt04-body: oklch(0.41 0.012 90);
--color-tpt04-mut: #6a665b;
--color-tpt04-mut: oklch(0.52 0.015 90);
--color-tpt04-acc: #d88a1e;
--color-tpt04-acc: oklch(0.7 0.15 65);
--color-tpt04-acc-ink: #9a5a00;
--color-tpt04-acc-ink: oklch(0.52 0.12 62);
--color-tpt04-on-acc: #1a1206;
--color-tpt04-on-acc: oklch(0.2 0.03 70);
--font-tpt04-sans: 'Bricolage Grotesque', system-ui, sans-serif;
--font-tpt04-mono: 'JetBrains Mono', ui-monospace, monospace;
}
/* Root rule: the full-bleed contract, stated in CSS as well as in the markup's utilities. */
.tpt-04 {
width: 100%;
min-height: 100svh;
}
/* The whole dark theme: re-point the tokens every utility already reads.
In production: [data-theme="dark"] .tpt-04 { … } */
.tpt-04:has(#tpt04-theme:checked) {
--color-tpt04-bg: #14130f;
--color-tpt04-bg: oklch(0.18 0.008 85);
--color-tpt04-surface: #1f1d17;
--color-tpt04-surface: oklch(0.225 0.01 85);
--color-tpt04-line: #36332a;
--color-tpt04-line: oklch(0.32 0.012 85);
--color-tpt04-ink: #f1eee3;
--color-tpt04-ink: oklch(0.95 0.012 90);
--color-tpt04-body: #cfcabb;
--color-tpt04-body: oklch(0.84 0.018 90);
--color-tpt04-mut: #a7a190;
--color-tpt04-mut: oklch(0.71 0.02 90);
--color-tpt04-acc: #f0b44a;
--color-tpt04-acc: oklch(0.8 0.14 75);
--color-tpt04-acc-ink: #f0b44a;
--color-tpt04-acc-ink: oklch(0.8 0.14 75);
}@import "tailwindcss";
@theme {
--color-tpt04-bg: #f4f2ec;
--color-tpt04-bg: oklch(0.96 0.008 90);
--color-tpt04-surface: #ffffff;
--color-tpt04-surface: oklch(1 0 0);
--color-tpt04-line: #e2dfd5;
--color-tpt04-line: oklch(0.9 0.012 90);
--color-tpt04-ink: #211f1a;
--color-tpt04-ink: oklch(0.23 0.01 90);
--color-tpt04-body: #4a473f;
--color-tpt04-body: oklch(0.41 0.012 90);
--color-tpt04-mut: #6a665b;
--color-tpt04-mut: oklch(0.52 0.015 90);
--color-tpt04-acc: #d88a1e;
--color-tpt04-acc: oklch(0.7 0.15 65);
--color-tpt04-acc-ink: #9a5a00;
--color-tpt04-acc-ink: oklch(0.52 0.12 62);
--color-tpt04-on-acc: #1a1206;
--color-tpt04-on-acc: oklch(0.2 0.03 70);
--font-tpt04-sans: 'Bricolage Grotesque', system-ui, sans-serif;
--font-tpt04-mono: 'JetBrains Mono', ui-monospace, monospace;
}
/* Root rule: the full-bleed contract, stated in CSS as well as in the markup's utilities. */
.tpt-04 {
width: 100%;
min-height: 100svh;
}
/* The whole dark theme: re-point the tokens every utility already reads.
In production: [data-theme="dark"] .tpt-04 { … } */
.tpt-04:has(#tpt04-theme:checked) {
--color-tpt04-bg: #14130f;
--color-tpt04-bg: oklch(0.18 0.008 85);
--color-tpt04-surface: #1f1d17;
--color-tpt04-surface: oklch(0.225 0.01 85);
--color-tpt04-line: #36332a;
--color-tpt04-line: oklch(0.32 0.012 85);
--color-tpt04-ink: #f1eee3;
--color-tpt04-ink: oklch(0.95 0.012 90);
--color-tpt04-body: #cfcabb;
--color-tpt04-body: oklch(0.84 0.018 90);
--color-tpt04-mut: #a7a190;
--color-tpt04-mut: oklch(0.71 0.02 90);
--color-tpt04-acc: #f0b44a;
--color-tpt04-acc: oklch(0.8 0.14 75);
--color-tpt04-acc-ink: #f0b44a;
--color-tpt04-acc-ink: oklch(0.8 0.14 75);
}<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=Bricolage+Grotesque:opsz,wght@12..96,400..800&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=Bricolage+Grotesque:opsz,wght@12..96,400..800&family=JetBrains+Mono:wght@400;500&display=swap">What changed in the port
Which parts became utilities, which stayed CSS, and why.
- The original's seven
--bg/--surface/…custom properties became@themetokens, which is what mintsbg-tpt04-surface,border-tpt04-lineand friends. - The single
:has(:checked)override stayed CSS — deliberately. It is one rule instead of ~40dark:duplicates, and it maps 1:1 onto a site-wide[data-theme]hook. - UI upgrade from the CSS original: the ☀/☾ text glyphs (which render as emoji on iOS) became stroked SVG icons in a 44px switch with
role="switch"; muted copy rose from#7a766a(4.1:1) to 5.1:1 in light and#9a9584to 6.3:1 in dark. - UI upgrade: the amber accent now has a darker
acc-inkfor text and checks in light mode, so “Craft” and the ticks clear AA; the display face moved to Bricolage Grotesque.
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 Dark Mode Pricing Cards with Light / Dark Toggle
Source: https://codefronts.com/components/tailwind-css-pricing-tables/tailwind-dark-mode-pricing-cards-toggle/
Theme-aware pricing, the v4 way: every utility reads an @theme token (bg-tpt04-surface, text-tpt04-mut…), so one CSS rule re-points the tokens and the whole component crossfades. No dark: class is duplicated on any element — the palette stays a palette, and the switch is a real role="switch".
## HTML
```html
<section class="tpt-04 group/p w-full min-h-svh grid place-items-center bg-tpt04-bg px-5 py-16 font-tpt04-sans text-tpt04-ink antialiased transition-colors duration-500" aria-label="Theme-adaptive pricing cards">
<div class="grid w-full max-w-5xl gap-9">
<header class="flex flex-wrap items-center justify-between gap-5">
<h2 class="text-[clamp(26px,3.8vw,40px)] font-extrabold tracking-[-0.03em]">Looks right in any theme</h2>
<input type="checkbox" id="tpt04-theme" role="switch" class="peer sr-only" aria-label="Dark theme">
<label for="tpt04-theme" class="relative flex h-11 cursor-pointer items-center gap-1 rounded-full border border-tpt04-line bg-tpt04-surface p-1 transition-colors duration-500 peer-focus-visible:outline-3 peer-focus-visible:outline-offset-3 peer-focus-visible:outline-tpt04-acc">
<span aria-hidden="true" class="absolute top-1 left-1 size-9 rounded-full bg-tpt04-acc/20 transition-transform duration-300 ease-[cubic-bezier(.5,1.5,.4,1)] group-has-checked/p:translate-x-10"></span>
<svg aria-hidden="true" class="relative size-9 p-2 text-tpt04-acc-ink transition-opacity group-has-checked/p:opacity-45" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"><circle cx="12" cy="12" r="4"/><path d="M12 2v2M12 20v2M4.9 4.9l1.4 1.4M17.7 17.7l1.4 1.4M2 12h2M20 12h2M4.9 19.1l1.4-1.4M17.7 6.3l1.4-1.4"/></svg>
<svg aria-hidden="true" class="relative size-9 p-2 text-tpt04-acc-ink opacity-45 transition-opacity group-has-checked/p:opacity-100" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M20 14.5A8 8 0 0 1 9.5 4 8 8 0 1 0 20 14.5z"/></svg>
</label>
</header>
<div class="grid gap-5 md:grid-cols-3">
<article class="flex flex-col gap-4 rounded-[20px] border border-tpt04-line bg-tpt04-surface p-7 transition-colors duration-500">
<h3 class="text-[13px] font-bold tracking-[0.08em] text-tpt04-mut uppercase transition-colors duration-500">Solo</h3>
<p class="text-[44px] leading-none font-extrabold tracking-[-0.035em]">$8<small class="text-[15px] font-semibold tracking-normal text-tpt04-mut">/mo</small></p>
<ul class="grid flex-1 content-start gap-2.5 text-sm text-tpt04-body transition-colors duration-500 *:flex *:gap-2.5 *:before:font-bold *:before:text-tpt04-acc-ink *:before:content-['✓']"><li>1 workspace</li><li>Core blocks</li><li>7-day history</li></ul>
<a href="#" class="grid min-h-11 place-items-center rounded-xl border-[1.5px] border-tpt04-line text-sm font-bold text-tpt04-ink no-underline transition-colors duration-300 hover:border-tpt04-acc focus-visible:outline-3 focus-visible:outline-offset-2 focus-visible:outline-tpt04-acc">Choose Solo</a>
</article>
<article class="relative flex flex-col gap-4 rounded-[20px] bg-tpt04-surface p-7 ring-2 ring-tpt04-acc transition-colors duration-500">
<span class="absolute -top-3 left-6 rounded-full bg-tpt04-acc px-3 py-1 text-[10.5px] font-bold tracking-[0.08em] text-tpt04-on-acc uppercase transition-colors duration-500">Most popular</span>
<h3 class="text-[13px] font-bold tracking-[0.08em] text-tpt04-acc-ink uppercase transition-colors duration-500">Craft</h3>
<p class="text-[44px] leading-none font-extrabold tracking-[-0.035em]">$20<small class="text-[15px] font-semibold tracking-normal text-tpt04-mut">/mo</small></p>
<ul class="grid flex-1 content-start gap-2.5 text-sm text-tpt04-body transition-colors duration-500 *:flex *:gap-2.5 *:before:font-bold *:before:text-tpt04-acc-ink *:before:content-['✓']"><li>5 workspaces</li><li>All blocks</li><li>Unlimited version history</li></ul>
<a href="#" class="grid min-h-11 place-items-center rounded-xl bg-tpt04-acc text-sm font-bold text-tpt04-on-acc no-underline transition duration-300 hover:brightness-105 focus-visible:outline-3 focus-visible:outline-offset-2 focus-visible:outline-tpt04-acc">Choose Craft</a>
</article>
<article class="flex flex-col gap-4 rounded-[20px] border border-tpt04-line bg-tpt04-surface p-7 transition-colors duration-500">
<h3 class="text-[13px] font-bold tracking-[0.08em] text-tpt04-mut uppercase transition-colors duration-500">Studio</h3>
<p class="text-[44px] leading-none font-extrabold tracking-[-0.035em]">$45<small class="text-[15px] font-semibold tracking-normal text-tpt04-mut">/mo</small></p>
<ul class="grid flex-1 content-start gap-2.5 text-sm text-tpt04-body transition-colors duration-500 *:flex *:gap-2.5 *:before:font-bold *:before:text-tpt04-acc-ink *:before:content-['✓']"><li>Unlimited workspaces</li><li>Team roles</li><li>Priority support</li></ul>
<a href="#" class="grid min-h-11 place-items-center rounded-xl border-[1.5px] border-tpt04-line text-sm font-bold text-tpt04-ink no-underline transition-colors duration-300 hover:border-tpt04-acc focus-visible:outline-3 focus-visible:outline-offset-2 focus-visible:outline-tpt04-acc">Choose Studio</a>
</article>
</div>
<p aria-hidden="true" class="justify-self-center rounded-full border border-tpt04-line px-3.5 py-2 font-tpt04-mono text-[11.5px] text-tpt04-mut transition-colors duration-500">@theme tokens · one swap rule · transition-colors</p>
</div>
</section>
```
## CSS
```css
@import "tailwindcss";
@theme {
--color-tpt04-bg: #f4f2ec;
--color-tpt04-bg: oklch(0.96 0.008 90);
--color-tpt04-surface: #ffffff;
--color-tpt04-surface: oklch(1 0 0);
--color-tpt04-line: #e2dfd5;
--color-tpt04-line: oklch(0.9 0.012 90);
--color-tpt04-ink: #211f1a;
--color-tpt04-ink: oklch(0.23 0.01 90);
--color-tpt04-body: #4a473f;
--color-tpt04-body: oklch(0.41 0.012 90);
--color-tpt04-mut: #6a665b;
--color-tpt04-mut: oklch(0.52 0.015 90);
--color-tpt04-acc: #d88a1e;
--color-tpt04-acc: oklch(0.7 0.15 65);
--color-tpt04-acc-ink: #9a5a00;
--color-tpt04-acc-ink: oklch(0.52 0.12 62);
--color-tpt04-on-acc: #1a1206;
--color-tpt04-on-acc: oklch(0.2 0.03 70);
--font-tpt04-sans: 'Bricolage Grotesque', system-ui, sans-serif;
--font-tpt04-mono: 'JetBrains Mono', ui-monospace, monospace;
}
/* Root rule: the full-bleed contract, stated in CSS as well as in the markup's utilities. */
.tpt-04 {
width: 100%;
min-height: 100svh;
}
/* The whole dark theme: re-point the tokens every utility already reads.
In production: [data-theme="dark"] .tpt-04 { … } */
.tpt-04:has(#tpt04-theme:checked) {
--color-tpt04-bg: #14130f;
--color-tpt04-bg: oklch(0.18 0.008 85);
--color-tpt04-surface: #1f1d17;
--color-tpt04-surface: oklch(0.225 0.01 85);
--color-tpt04-line: #36332a;
--color-tpt04-line: oklch(0.32 0.012 85);
--color-tpt04-ink: #f1eee3;
--color-tpt04-ink: oklch(0.95 0.012 90);
--color-tpt04-body: #cfcabb;
--color-tpt04-body: oklch(0.84 0.018 90);
--color-tpt04-mut: #a7a190;
--color-tpt04-mut: oklch(0.71 0.02 90);
--color-tpt04-acc: #f0b44a;
--color-tpt04-acc: oklch(0.8 0.14 75);
--color-tpt04-acc-ink: #f0b44a;
--color-tpt04-acc-ink: oklch(0.8 0.14 75);
}
```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 Dark Mode Pricing Cards with Light / Dark Toggle
Source: https://codefronts.com/components/tailwind-css-pricing-tables/tailwind-dark-mode-pricing-cards-toggle/
Theme-aware pricing, the v4 way: every utility reads an @theme token (bg-tpt04-surface, text-tpt04-mut…), so one CSS rule re-points the tokens and the whole component crossfades. No dark: class is duplicated on any element — the palette stays a palette, and the switch is a real role="switch".
## HTML
```html
<section class="tpt-04 group/p w-full min-h-svh grid place-items-center bg-tpt04-bg px-5 py-16 font-tpt04-sans text-tpt04-ink antialiased transition-colors duration-500" aria-label="Theme-adaptive pricing cards">
<div class="grid w-full max-w-5xl gap-9">
<header class="flex flex-wrap items-center justify-between gap-5">
<h2 class="text-[clamp(26px,3.8vw,40px)] font-extrabold tracking-[-0.03em]">Looks right in any theme</h2>
<input type="checkbox" id="tpt04-theme" role="switch" class="peer sr-only" aria-label="Dark theme">
<label for="tpt04-theme" class="relative flex h-11 cursor-pointer items-center gap-1 rounded-full border border-tpt04-line bg-tpt04-surface p-1 transition-colors duration-500 peer-focus-visible:outline-3 peer-focus-visible:outline-offset-3 peer-focus-visible:outline-tpt04-acc">
<span aria-hidden="true" class="absolute top-1 left-1 size-9 rounded-full bg-tpt04-acc/20 transition-transform duration-300 ease-[cubic-bezier(.5,1.5,.4,1)] group-has-checked/p:translate-x-10"></span>
<svg aria-hidden="true" class="relative size-9 p-2 text-tpt04-acc-ink transition-opacity group-has-checked/p:opacity-45" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"><circle cx="12" cy="12" r="4"/><path d="M12 2v2M12 20v2M4.9 4.9l1.4 1.4M17.7 17.7l1.4 1.4M2 12h2M20 12h2M4.9 19.1l1.4-1.4M17.7 6.3l1.4-1.4"/></svg>
<svg aria-hidden="true" class="relative size-9 p-2 text-tpt04-acc-ink opacity-45 transition-opacity group-has-checked/p:opacity-100" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M20 14.5A8 8 0 0 1 9.5 4 8 8 0 1 0 20 14.5z"/></svg>
</label>
</header>
<div class="grid gap-5 md:grid-cols-3">
<article class="flex flex-col gap-4 rounded-[20px] border border-tpt04-line bg-tpt04-surface p-7 transition-colors duration-500">
<h3 class="text-[13px] font-bold tracking-[0.08em] text-tpt04-mut uppercase transition-colors duration-500">Solo</h3>
<p class="text-[44px] leading-none font-extrabold tracking-[-0.035em]">$8<small class="text-[15px] font-semibold tracking-normal text-tpt04-mut">/mo</small></p>
<ul class="grid flex-1 content-start gap-2.5 text-sm text-tpt04-body transition-colors duration-500 *:flex *:gap-2.5 *:before:font-bold *:before:text-tpt04-acc-ink *:before:content-['✓']"><li>1 workspace</li><li>Core blocks</li><li>7-day history</li></ul>
<a href="#" class="grid min-h-11 place-items-center rounded-xl border-[1.5px] border-tpt04-line text-sm font-bold text-tpt04-ink no-underline transition-colors duration-300 hover:border-tpt04-acc focus-visible:outline-3 focus-visible:outline-offset-2 focus-visible:outline-tpt04-acc">Choose Solo</a>
</article>
<article class="relative flex flex-col gap-4 rounded-[20px] bg-tpt04-surface p-7 ring-2 ring-tpt04-acc transition-colors duration-500">
<span class="absolute -top-3 left-6 rounded-full bg-tpt04-acc px-3 py-1 text-[10.5px] font-bold tracking-[0.08em] text-tpt04-on-acc uppercase transition-colors duration-500">Most popular</span>
<h3 class="text-[13px] font-bold tracking-[0.08em] text-tpt04-acc-ink uppercase transition-colors duration-500">Craft</h3>
<p class="text-[44px] leading-none font-extrabold tracking-[-0.035em]">$20<small class="text-[15px] font-semibold tracking-normal text-tpt04-mut">/mo</small></p>
<ul class="grid flex-1 content-start gap-2.5 text-sm text-tpt04-body transition-colors duration-500 *:flex *:gap-2.5 *:before:font-bold *:before:text-tpt04-acc-ink *:before:content-['✓']"><li>5 workspaces</li><li>All blocks</li><li>Unlimited version history</li></ul>
<a href="#" class="grid min-h-11 place-items-center rounded-xl bg-tpt04-acc text-sm font-bold text-tpt04-on-acc no-underline transition duration-300 hover:brightness-105 focus-visible:outline-3 focus-visible:outline-offset-2 focus-visible:outline-tpt04-acc">Choose Craft</a>
</article>
<article class="flex flex-col gap-4 rounded-[20px] border border-tpt04-line bg-tpt04-surface p-7 transition-colors duration-500">
<h3 class="text-[13px] font-bold tracking-[0.08em] text-tpt04-mut uppercase transition-colors duration-500">Studio</h3>
<p class="text-[44px] leading-none font-extrabold tracking-[-0.035em]">$45<small class="text-[15px] font-semibold tracking-normal text-tpt04-mut">/mo</small></p>
<ul class="grid flex-1 content-start gap-2.5 text-sm text-tpt04-body transition-colors duration-500 *:flex *:gap-2.5 *:before:font-bold *:before:text-tpt04-acc-ink *:before:content-['✓']"><li>Unlimited workspaces</li><li>Team roles</li><li>Priority support</li></ul>
<a href="#" class="grid min-h-11 place-items-center rounded-xl border-[1.5px] border-tpt04-line text-sm font-bold text-tpt04-ink no-underline transition-colors duration-300 hover:border-tpt04-acc focus-visible:outline-3 focus-visible:outline-offset-2 focus-visible:outline-tpt04-acc">Choose Studio</a>
</article>
</div>
<p aria-hidden="true" class="justify-self-center rounded-full border border-tpt04-line px-3.5 py-2 font-tpt04-mono text-[11.5px] text-tpt04-mut transition-colors duration-500">@theme tokens · one swap rule · transition-colors</p>
</div>
</section>
```
## CSS
```css
@import "tailwindcss";
@theme {
--color-tpt04-bg: #f4f2ec;
--color-tpt04-bg: oklch(0.96 0.008 90);
--color-tpt04-surface: #ffffff;
--color-tpt04-surface: oklch(1 0 0);
--color-tpt04-line: #e2dfd5;
--color-tpt04-line: oklch(0.9 0.012 90);
--color-tpt04-ink: #211f1a;
--color-tpt04-ink: oklch(0.23 0.01 90);
--color-tpt04-body: #4a473f;
--color-tpt04-body: oklch(0.41 0.012 90);
--color-tpt04-mut: #6a665b;
--color-tpt04-mut: oklch(0.52 0.015 90);
--color-tpt04-acc: #d88a1e;
--color-tpt04-acc: oklch(0.7 0.15 65);
--color-tpt04-acc-ink: #9a5a00;
--color-tpt04-acc-ink: oklch(0.52 0.12 62);
--color-tpt04-on-acc: #1a1206;
--color-tpt04-on-acc: oklch(0.2 0.03 70);
--font-tpt04-sans: 'Bricolage Grotesque', system-ui, sans-serif;
--font-tpt04-mono: 'JetBrains Mono', ui-monospace, monospace;
}
/* Root rule: the full-bleed contract, stated in CSS as well as in the markup's utilities. */
.tpt-04 {
width: 100%;
min-height: 100svh;
}
/* The whole dark theme: re-point the tokens every utility already reads.
In production: [data-theme="dark"] .tpt-04 { … } */
.tpt-04:has(#tpt04-theme:checked) {
--color-tpt04-bg: #14130f;
--color-tpt04-bg: oklch(0.18 0.008 85);
--color-tpt04-surface: #1f1d17;
--color-tpt04-surface: oklch(0.225 0.01 85);
--color-tpt04-line: #36332a;
--color-tpt04-line: oklch(0.32 0.012 85);
--color-tpt04-ink: #f1eee3;
--color-tpt04-ink: oklch(0.95 0.012 90);
--color-tpt04-body: #cfcabb;
--color-tpt04-body: oklch(0.84 0.018 90);
--color-tpt04-mut: #a7a190;
--color-tpt04-mut: oklch(0.71 0.02 90);
--color-tpt04-acc: #f0b44a;
--color-tpt04-acc: oklch(0.8 0.14 75);
--color-tpt04-acc-ink: #f0b44a;
--color-tpt04-acc-ink: oklch(0.8 0.14 75);
}
```How this works
Tokens, not variants. The idiomatic dark: approach would double every colour class (bg-white dark:bg-stone-900). Because Tailwind v4 compiles theme utilities to CSS variables, you can instead swap the variables:
.tpt-04:has(#tpt04-theme:checked) {
--color-tpt04-bg: oklch(0.18 0.01 80);
--color-tpt04-surface: oklch(0.22 0.012 80);
…
}Production wiring. Replace the local checkbox with your site's toggle: point the same rule at [data-theme=dark] .tpt-04, or register @custom-variant dark (&:where([data-theme=dark], [data-theme=dark] *)); for the rest of your app.
Both themes pass AA. Muted copy is 5.1:1 in light and 6.3:1 in dark.
Make it yours
- Follow the OS: duplicate the token block inside
@media (prefers-color-scheme:dark). - Add a token (e.g.
--color-tpt04-ok) and both themes stay in sync automatically. - Change crossfade speed with
duration-500on the themed elements. - Tint the featured card differently per theme by adding a
--color-tpt04-hottoken.
Gotchas — read before shipping
- Tailwind emits theme tokens on
:root; overriding them on.tpt-04works because utilities readvar()at use time. Using@theme inlinewould bake the values in and break the swap. - Gradients can't tween, so the featured card uses a solid ring, not a gradient border.
- Don't put
transition-colorson huge trees; scope it to themed surfaces as here.
Browser support
| Chrome | Safari | Firefox | Edge |
|---|---|---|---|
| 111+ | 16.4+ | 128+ | 111+ |
The local toggle uses :has(); driving the swap from a data-theme attribute drops that requirement.