16 / 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 Pricing Card with Animated Gradient Border on Hover
Hover a clean minimal card and a pink-to-violet-to-cyan border draws itself clockwise from twelve o'clock, then un-draws when you leave. The border is one arbitrary [background:…] utility using the padding-box / border-box trick; its visible arc length is a registered @property percentage, transitioned by hover:[--tpt16-p:100%].
Complete Tailwind CSS landing page templates in HTML, React, Next.js and Vue · from $49
Cruip · Affiliate link
The code
<section class="tpt-16 w-full min-h-svh grid place-items-center bg-tpt16-bg px-5 py-16 font-tpt16-sans text-tpt16-ink antialiased" aria-label="Pricing cards with gradient border draw effect">
<div class="grid w-full max-w-5xl justify-items-center gap-10">
<h2 class="text-center text-[clamp(26px,3.8vw,40px)] font-bold tracking-[-0.03em]">Sketch it. Ship it.</h2>
<div class="grid w-full gap-5 md:grid-cols-3">
<article class="flex flex-col gap-1.5 rounded-[20px] border-2 border-transparent p-8 [background:linear-gradient(white,white)_padding-box,conic-gradient(from_-90deg,var(--color-tpt16-c1),var(--color-tpt16-c2)_calc(var(--tpt16-p)*.5),var(--color-tpt16-c3)_var(--tpt16-p),var(--color-tpt16-line)_0)_border-box] [transition:--tpt16-p_800ms_cubic-bezier(.5,0,.2,1),box-shadow_350ms] hover:shadow-[0_20px_44px_-28px_var(--color-tpt16-c2)] hover:[--tpt16-p:100%] focus-within:[--tpt16-p:100%] motion-reduce:[transition:none]">
<h3 class="text-[13px] font-semibold tracking-[0.08em] text-tpt16-mut uppercase">Sketch</h3>
<p class="text-[44px] leading-tight font-bold tracking-[-0.035em]">$11<small class="text-[15px] font-medium tracking-normal text-tpt16-mut">/mo</small></p>
<ul class="mt-3 mb-6 grid flex-1 content-start gap-2.5 text-sm text-tpt16-body *:flex *:gap-2.5 *:before:text-tpt16-c2 *:before:content-['→']"><li>3 boards</li><li>PNG export</li><li>Version history</li></ul>
<a href="#" class="grid min-h-11 place-items-center rounded-xl bg-tpt16-ink text-sm font-semibold text-white no-underline transition hover:bg-linear-to-r hover:from-tpt16-c1 hover:via-tpt16-c2 hover:to-tpt16-c3-ink focus-visible:outline-3 focus-visible:outline-offset-2 focus-visible:outline-tpt16-c2">Start Sketch</a>
</article>
<article class="relative flex flex-col gap-1.5 rounded-[20px] border-2 border-transparent p-8 [--tpt16-p:22%] [background:linear-gradient(white,white)_padding-box,conic-gradient(from_-90deg,var(--color-tpt16-c1),var(--color-tpt16-c2)_calc(var(--tpt16-p)*.5),var(--color-tpt16-c3)_var(--tpt16-p),var(--color-tpt16-line)_0)_border-box] [transition:--tpt16-p_800ms_cubic-bezier(.5,0,.2,1),box-shadow_350ms] hover:shadow-[0_20px_44px_-28px_var(--color-tpt16-c2)] hover:[--tpt16-p:100%] focus-within:[--tpt16-p:100%] motion-reduce:[transition:none]">
<span class="absolute -top-3 left-8 rounded-full bg-linear-to-r from-tpt16-c1 to-tpt16-c2 px-3 py-1 text-[10.5px] font-bold tracking-[0.08em] text-white uppercase">Most popular</span>
<h3 class="text-[13px] font-semibold tracking-[0.08em] text-tpt16-c2 uppercase">Draft</h3>
<p class="text-[44px] leading-tight font-bold tracking-[-0.035em]">$27<small class="text-[15px] font-medium tracking-normal text-tpt16-mut">/mo</small></p>
<ul class="mt-3 mb-6 grid flex-1 content-start gap-2.5 text-sm text-tpt16-body *:flex *:gap-2.5 *:before:text-tpt16-c2 *:before:content-['→']"><li>Unlimited boards</li><li>SVG + PDF export</li><li>Comments & mentions</li></ul>
<a href="#" class="grid min-h-11 place-items-center rounded-xl bg-tpt16-ink text-sm font-semibold text-white no-underline transition hover:bg-linear-to-r hover:from-tpt16-c1 hover:via-tpt16-c2 hover:to-tpt16-c3-ink focus-visible:outline-3 focus-visible:outline-offset-2 focus-visible:outline-tpt16-c2">Start Draft</a>
</article>
<article class="flex flex-col gap-1.5 rounded-[20px] border-2 border-transparent p-8 [background:linear-gradient(white,white)_padding-box,conic-gradient(from_-90deg,var(--color-tpt16-c1),var(--color-tpt16-c2)_calc(var(--tpt16-p)*.5),var(--color-tpt16-c3)_var(--tpt16-p),var(--color-tpt16-line)_0)_border-box] [transition:--tpt16-p_800ms_cubic-bezier(.5,0,.2,1),box-shadow_350ms] hover:shadow-[0_20px_44px_-28px_var(--color-tpt16-c2)] hover:[--tpt16-p:100%] focus-within:[--tpt16-p:100%] motion-reduce:[transition:none]">
<h3 class="text-[13px] font-semibold tracking-[0.08em] text-tpt16-mut uppercase">Studio</h3>
<p class="text-[44px] leading-tight font-bold tracking-[-0.035em]">$68<small class="text-[15px] font-medium tracking-normal text-tpt16-mut">/mo</small></p>
<ul class="mt-3 mb-6 grid flex-1 content-start gap-2.5 text-sm text-tpt16-body *:flex *:gap-2.5 *:before:text-tpt16-c2 *:before:content-['→']"><li>Everything in Draft</li><li>Team libraries</li><li>SSO</li></ul>
<a href="#" class="grid min-h-11 place-items-center rounded-xl bg-tpt16-ink text-sm font-semibold text-white no-underline transition hover:bg-linear-to-r hover:from-tpt16-c1 hover:via-tpt16-c2 hover:to-tpt16-c3-ink focus-visible:outline-3 focus-visible:outline-offset-2 focus-visible:outline-tpt16-c2">Start Studio</a>
</article>
</div>
<p aria-hidden="true" class="rounded-full border border-tpt16-line bg-white px-3.5 py-2 font-tpt16-mono text-[11.5px] text-tpt16-mut">@property --tpt16-p · hover:[--tpt16-p:100%] · padding-box / border-box</p>
</div>
</section><section class="tpt-16 w-full min-h-svh grid place-items-center bg-tpt16-bg px-5 py-16 font-tpt16-sans text-tpt16-ink antialiased" aria-label="Pricing cards with gradient border draw effect">
<div class="grid w-full max-w-5xl justify-items-center gap-10">
<h2 class="text-center text-[clamp(26px,3.8vw,40px)] font-bold tracking-[-0.03em]">Sketch it. Ship it.</h2>
<div class="grid w-full gap-5 md:grid-cols-3">
<article class="flex flex-col gap-1.5 rounded-[20px] border-2 border-transparent p-8 [background:linear-gradient(white,white)_padding-box,conic-gradient(from_-90deg,var(--color-tpt16-c1),var(--color-tpt16-c2)_calc(var(--tpt16-p)*.5),var(--color-tpt16-c3)_var(--tpt16-p),var(--color-tpt16-line)_0)_border-box] [transition:--tpt16-p_800ms_cubic-bezier(.5,0,.2,1),box-shadow_350ms] hover:shadow-[0_20px_44px_-28px_var(--color-tpt16-c2)] hover:[--tpt16-p:100%] focus-within:[--tpt16-p:100%] motion-reduce:[transition:none]">
<h3 class="text-[13px] font-semibold tracking-[0.08em] text-tpt16-mut uppercase">Sketch</h3>
<p class="text-[44px] leading-tight font-bold tracking-[-0.035em]">$11<small class="text-[15px] font-medium tracking-normal text-tpt16-mut">/mo</small></p>
<ul class="mt-3 mb-6 grid flex-1 content-start gap-2.5 text-sm text-tpt16-body *:flex *:gap-2.5 *:before:text-tpt16-c2 *:before:content-['→']"><li>3 boards</li><li>PNG export</li><li>Version history</li></ul>
<a href="#" class="grid min-h-11 place-items-center rounded-xl bg-tpt16-ink text-sm font-semibold text-white no-underline transition hover:bg-linear-to-r hover:from-tpt16-c1 hover:via-tpt16-c2 hover:to-tpt16-c3-ink focus-visible:outline-3 focus-visible:outline-offset-2 focus-visible:outline-tpt16-c2">Start Sketch</a>
</article>
<article class="relative flex flex-col gap-1.5 rounded-[20px] border-2 border-transparent p-8 [--tpt16-p:22%] [background:linear-gradient(white,white)_padding-box,conic-gradient(from_-90deg,var(--color-tpt16-c1),var(--color-tpt16-c2)_calc(var(--tpt16-p)*.5),var(--color-tpt16-c3)_var(--tpt16-p),var(--color-tpt16-line)_0)_border-box] [transition:--tpt16-p_800ms_cubic-bezier(.5,0,.2,1),box-shadow_350ms] hover:shadow-[0_20px_44px_-28px_var(--color-tpt16-c2)] hover:[--tpt16-p:100%] focus-within:[--tpt16-p:100%] motion-reduce:[transition:none]">
<span class="absolute -top-3 left-8 rounded-full bg-linear-to-r from-tpt16-c1 to-tpt16-c2 px-3 py-1 text-[10.5px] font-bold tracking-[0.08em] text-white uppercase">Most popular</span>
<h3 class="text-[13px] font-semibold tracking-[0.08em] text-tpt16-c2 uppercase">Draft</h3>
<p class="text-[44px] leading-tight font-bold tracking-[-0.035em]">$27<small class="text-[15px] font-medium tracking-normal text-tpt16-mut">/mo</small></p>
<ul class="mt-3 mb-6 grid flex-1 content-start gap-2.5 text-sm text-tpt16-body *:flex *:gap-2.5 *:before:text-tpt16-c2 *:before:content-['→']"><li>Unlimited boards</li><li>SVG + PDF export</li><li>Comments & mentions</li></ul>
<a href="#" class="grid min-h-11 place-items-center rounded-xl bg-tpt16-ink text-sm font-semibold text-white no-underline transition hover:bg-linear-to-r hover:from-tpt16-c1 hover:via-tpt16-c2 hover:to-tpt16-c3-ink focus-visible:outline-3 focus-visible:outline-offset-2 focus-visible:outline-tpt16-c2">Start Draft</a>
</article>
<article class="flex flex-col gap-1.5 rounded-[20px] border-2 border-transparent p-8 [background:linear-gradient(white,white)_padding-box,conic-gradient(from_-90deg,var(--color-tpt16-c1),var(--color-tpt16-c2)_calc(var(--tpt16-p)*.5),var(--color-tpt16-c3)_var(--tpt16-p),var(--color-tpt16-line)_0)_border-box] [transition:--tpt16-p_800ms_cubic-bezier(.5,0,.2,1),box-shadow_350ms] hover:shadow-[0_20px_44px_-28px_var(--color-tpt16-c2)] hover:[--tpt16-p:100%] focus-within:[--tpt16-p:100%] motion-reduce:[transition:none]">
<h3 class="text-[13px] font-semibold tracking-[0.08em] text-tpt16-mut uppercase">Studio</h3>
<p class="text-[44px] leading-tight font-bold tracking-[-0.035em]">$68<small class="text-[15px] font-medium tracking-normal text-tpt16-mut">/mo</small></p>
<ul class="mt-3 mb-6 grid flex-1 content-start gap-2.5 text-sm text-tpt16-body *:flex *:gap-2.5 *:before:text-tpt16-c2 *:before:content-['→']"><li>Everything in Draft</li><li>Team libraries</li><li>SSO</li></ul>
<a href="#" class="grid min-h-11 place-items-center rounded-xl bg-tpt16-ink text-sm font-semibold text-white no-underline transition hover:bg-linear-to-r hover:from-tpt16-c1 hover:via-tpt16-c2 hover:to-tpt16-c3-ink focus-visible:outline-3 focus-visible:outline-offset-2 focus-visible:outline-tpt16-c2">Start Studio</a>
</article>
</div>
<p aria-hidden="true" class="rounded-full border border-tpt16-line bg-white px-3.5 py-2 font-tpt16-mono text-[11.5px] text-tpt16-mut">@property --tpt16-p · hover:[--tpt16-p:100%] · padding-box / border-box</p>
</div>
</section>@import "tailwindcss";
@theme {
--color-tpt16-bg: #fafafa;
--color-tpt16-bg: oklch(0.985 0 0);
--color-tpt16-ink: #191919;
--color-tpt16-ink: oklch(0.21 0 0);
--color-tpt16-body: #474747;
--color-tpt16-body: oklch(0.42 0 0);
--color-tpt16-mut: #6b6b6b;
--color-tpt16-mut: oklch(0.53 0 0);
--color-tpt16-line: #e8e8e8;
--color-tpt16-line: oklch(0.93 0 0);
--color-tpt16-c1: #e8338a;
--color-tpt16-c1: oklch(0.62 0.23 355);
--color-tpt16-c2: #6a3fe0;
--color-tpt16-c2: oklch(0.53 0.22 285);
--color-tpt16-c3: #19b3d6;
--color-tpt16-c3: oklch(0.71 0.13 215);
--color-tpt16-c3-ink: #0f7f9c;
--color-tpt16-c3-ink: oklch(0.55 0.1 220);
--font-tpt16-sans: 'Space Grotesk', system-ui, sans-serif;
--font-tpt16-mono: 'JetBrains Mono', ui-monospace, monospace;
}
/* Root rule: the full-bleed contract, stated in CSS as well as in the markup's utilities. */
.tpt-16 {
width: 100%;
min-height: 100svh;
}
/* Registered so the arc length can transition. */
@property --tpt16-p {
syntax: '<percentage>';
initial-value: 0%;
inherits: false;
}@import "tailwindcss";
@theme {
--color-tpt16-bg: #fafafa;
--color-tpt16-bg: oklch(0.985 0 0);
--color-tpt16-ink: #191919;
--color-tpt16-ink: oklch(0.21 0 0);
--color-tpt16-body: #474747;
--color-tpt16-body: oklch(0.42 0 0);
--color-tpt16-mut: #6b6b6b;
--color-tpt16-mut: oklch(0.53 0 0);
--color-tpt16-line: #e8e8e8;
--color-tpt16-line: oklch(0.93 0 0);
--color-tpt16-c1: #e8338a;
--color-tpt16-c1: oklch(0.62 0.23 355);
--color-tpt16-c2: #6a3fe0;
--color-tpt16-c2: oklch(0.53 0.22 285);
--color-tpt16-c3: #19b3d6;
--color-tpt16-c3: oklch(0.71 0.13 215);
--color-tpt16-c3-ink: #0f7f9c;
--color-tpt16-c3-ink: oklch(0.55 0.1 220);
--font-tpt16-sans: 'Space Grotesk', system-ui, sans-serif;
--font-tpt16-mono: 'JetBrains Mono', ui-monospace, monospace;
}
/* Root rule: the full-bleed contract, stated in CSS as well as in the markup's utilities. */
.tpt-16 {
width: 100%;
min-height: 100svh;
}
/* Registered so the arc length can transition. */
@property --tpt16-p {
syntax: '<percentage>';
initial-value: 0%;
inherits: false;
}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-tpt16-bg: #fafafa;
--color-tpt16-bg: oklch(0.985 0 0);
--color-tpt16-ink: #191919;
--color-tpt16-ink: oklch(0.21 0 0);
--color-tpt16-body: #474747;
--color-tpt16-body: oklch(0.42 0 0);
--color-tpt16-mut: #6b6b6b;
--color-tpt16-mut: oklch(0.53 0 0);
--color-tpt16-line: #e8e8e8;
--color-tpt16-line: oklch(0.93 0 0);
--color-tpt16-c1: #e8338a;
--color-tpt16-c1: oklch(0.62 0.23 355);
--color-tpt16-c2: #6a3fe0;
--color-tpt16-c2: oklch(0.53 0.22 285);
--color-tpt16-c3: #19b3d6;
--color-tpt16-c3: oklch(0.71 0.13 215);
--color-tpt16-c3-ink: #0f7f9c;
--color-tpt16-c3-ink: oklch(0.55 0.1 220);
--font-tpt16-sans: 'Space Grotesk', system-ui, sans-serif;
--font-tpt16-mono: 'JetBrains Mono', ui-monospace, monospace;
}
/* Root rule: the full-bleed contract, stated in CSS as well as in the markup's utilities. */
.tpt-16 {
width: 100%;
min-height: 100svh;
}
/* Registered so the arc length can transition. */
@property --tpt16-p {
syntax: '<percentage>';
initial-value: 0%;
inherits: false;
}@import "tailwindcss";
@theme {
--color-tpt16-bg: #fafafa;
--color-tpt16-bg: oklch(0.985 0 0);
--color-tpt16-ink: #191919;
--color-tpt16-ink: oklch(0.21 0 0);
--color-tpt16-body: #474747;
--color-tpt16-body: oklch(0.42 0 0);
--color-tpt16-mut: #6b6b6b;
--color-tpt16-mut: oklch(0.53 0 0);
--color-tpt16-line: #e8e8e8;
--color-tpt16-line: oklch(0.93 0 0);
--color-tpt16-c1: #e8338a;
--color-tpt16-c1: oklch(0.62 0.23 355);
--color-tpt16-c2: #6a3fe0;
--color-tpt16-c2: oklch(0.53 0.22 285);
--color-tpt16-c3: #19b3d6;
--color-tpt16-c3: oklch(0.71 0.13 215);
--color-tpt16-c3-ink: #0f7f9c;
--color-tpt16-c3-ink: oklch(0.55 0.1 220);
--font-tpt16-sans: 'Space Grotesk', system-ui, sans-serif;
--font-tpt16-mono: 'JetBrains Mono', ui-monospace, monospace;
}
/* Root rule: the full-bleed contract, stated in CSS as well as in the markup's utilities. */
.tpt-16 {
width: 100%;
min-height: 100svh;
}
/* Registered so the arc length can transition. */
@property --tpt16-p {
syntax: '<percentage>';
initial-value: 0%;
inherits: false;
}<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=Space+Grotesk: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=Space+Grotesk: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.
- The masked
::beforering (and its-webkit-mask-composite:xortwin) became a single[background:…]utility on the card using padding-box / border-box — no pseudo-element, no prefixes. transition:--prc16-p .8sbecame an arbitrary[transition:--tpt16-p_800ms_…];@propertystayed in CSS.- UI upgrade from the CSS original: the popular plan rests with a 22% arc already drawn, a quiet hint of what hovering does, and a gradient Most popular flag.
- UI upgrade: the CTA fills with the same gradient on hover so card and button feel like one gesture; muted copy rose from
#8a8a8a(3.4:1) to 5.3: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 Pricing Card with Animated Gradient Border on Hover
Source: https://codefronts.com/components/tailwind-css-pricing-tables/tailwind-pricing-card-animated-gradient-border-hover/
Hover a clean minimal card and a pink-to-violet-to-cyan border draws itself clockwise from twelve o'clock, then un-draws when you leave. The border is one arbitrary [background:…] utility using the padding-box / border-box trick; its visible arc length is a registered @property percentage, transitioned by hover:[--tpt16-p:100%].
## HTML
```html
<section class="tpt-16 w-full min-h-svh grid place-items-center bg-tpt16-bg px-5 py-16 font-tpt16-sans text-tpt16-ink antialiased" aria-label="Pricing cards with gradient border draw effect">
<div class="grid w-full max-w-5xl justify-items-center gap-10">
<h2 class="text-center text-[clamp(26px,3.8vw,40px)] font-bold tracking-[-0.03em]">Sketch it. Ship it.</h2>
<div class="grid w-full gap-5 md:grid-cols-3">
<article class="flex flex-col gap-1.5 rounded-[20px] border-2 border-transparent p-8 [background:linear-gradient(white,white)_padding-box,conic-gradient(from_-90deg,var(--color-tpt16-c1),var(--color-tpt16-c2)_calc(var(--tpt16-p)*.5),var(--color-tpt16-c3)_var(--tpt16-p),var(--color-tpt16-line)_0)_border-box] [transition:--tpt16-p_800ms_cubic-bezier(.5,0,.2,1),box-shadow_350ms] hover:shadow-[0_20px_44px_-28px_var(--color-tpt16-c2)] hover:[--tpt16-p:100%] focus-within:[--tpt16-p:100%] motion-reduce:[transition:none]">
<h3 class="text-[13px] font-semibold tracking-[0.08em] text-tpt16-mut uppercase">Sketch</h3>
<p class="text-[44px] leading-tight font-bold tracking-[-0.035em]">$11<small class="text-[15px] font-medium tracking-normal text-tpt16-mut">/mo</small></p>
<ul class="mt-3 mb-6 grid flex-1 content-start gap-2.5 text-sm text-tpt16-body *:flex *:gap-2.5 *:before:text-tpt16-c2 *:before:content-['→']"><li>3 boards</li><li>PNG export</li><li>Version history</li></ul>
<a href="#" class="grid min-h-11 place-items-center rounded-xl bg-tpt16-ink text-sm font-semibold text-white no-underline transition hover:bg-linear-to-r hover:from-tpt16-c1 hover:via-tpt16-c2 hover:to-tpt16-c3-ink focus-visible:outline-3 focus-visible:outline-offset-2 focus-visible:outline-tpt16-c2">Start Sketch</a>
</article>
<article class="relative flex flex-col gap-1.5 rounded-[20px] border-2 border-transparent p-8 [--tpt16-p:22%] [background:linear-gradient(white,white)_padding-box,conic-gradient(from_-90deg,var(--color-tpt16-c1),var(--color-tpt16-c2)_calc(var(--tpt16-p)*.5),var(--color-tpt16-c3)_var(--tpt16-p),var(--color-tpt16-line)_0)_border-box] [transition:--tpt16-p_800ms_cubic-bezier(.5,0,.2,1),box-shadow_350ms] hover:shadow-[0_20px_44px_-28px_var(--color-tpt16-c2)] hover:[--tpt16-p:100%] focus-within:[--tpt16-p:100%] motion-reduce:[transition:none]">
<span class="absolute -top-3 left-8 rounded-full bg-linear-to-r from-tpt16-c1 to-tpt16-c2 px-3 py-1 text-[10.5px] font-bold tracking-[0.08em] text-white uppercase">Most popular</span>
<h3 class="text-[13px] font-semibold tracking-[0.08em] text-tpt16-c2 uppercase">Draft</h3>
<p class="text-[44px] leading-tight font-bold tracking-[-0.035em]">$27<small class="text-[15px] font-medium tracking-normal text-tpt16-mut">/mo</small></p>
<ul class="mt-3 mb-6 grid flex-1 content-start gap-2.5 text-sm text-tpt16-body *:flex *:gap-2.5 *:before:text-tpt16-c2 *:before:content-['→']"><li>Unlimited boards</li><li>SVG + PDF export</li><li>Comments & mentions</li></ul>
<a href="#" class="grid min-h-11 place-items-center rounded-xl bg-tpt16-ink text-sm font-semibold text-white no-underline transition hover:bg-linear-to-r hover:from-tpt16-c1 hover:via-tpt16-c2 hover:to-tpt16-c3-ink focus-visible:outline-3 focus-visible:outline-offset-2 focus-visible:outline-tpt16-c2">Start Draft</a>
</article>
<article class="flex flex-col gap-1.5 rounded-[20px] border-2 border-transparent p-8 [background:linear-gradient(white,white)_padding-box,conic-gradient(from_-90deg,var(--color-tpt16-c1),var(--color-tpt16-c2)_calc(var(--tpt16-p)*.5),var(--color-tpt16-c3)_var(--tpt16-p),var(--color-tpt16-line)_0)_border-box] [transition:--tpt16-p_800ms_cubic-bezier(.5,0,.2,1),box-shadow_350ms] hover:shadow-[0_20px_44px_-28px_var(--color-tpt16-c2)] hover:[--tpt16-p:100%] focus-within:[--tpt16-p:100%] motion-reduce:[transition:none]">
<h3 class="text-[13px] font-semibold tracking-[0.08em] text-tpt16-mut uppercase">Studio</h3>
<p class="text-[44px] leading-tight font-bold tracking-[-0.035em]">$68<small class="text-[15px] font-medium tracking-normal text-tpt16-mut">/mo</small></p>
<ul class="mt-3 mb-6 grid flex-1 content-start gap-2.5 text-sm text-tpt16-body *:flex *:gap-2.5 *:before:text-tpt16-c2 *:before:content-['→']"><li>Everything in Draft</li><li>Team libraries</li><li>SSO</li></ul>
<a href="#" class="grid min-h-11 place-items-center rounded-xl bg-tpt16-ink text-sm font-semibold text-white no-underline transition hover:bg-linear-to-r hover:from-tpt16-c1 hover:via-tpt16-c2 hover:to-tpt16-c3-ink focus-visible:outline-3 focus-visible:outline-offset-2 focus-visible:outline-tpt16-c2">Start Studio</a>
</article>
</div>
<p aria-hidden="true" class="rounded-full border border-tpt16-line bg-white px-3.5 py-2 font-tpt16-mono text-[11.5px] text-tpt16-mut">@property --tpt16-p · hover:[--tpt16-p:100%] · padding-box / border-box</p>
</div>
</section>
```
## CSS
```css
@import "tailwindcss";
@theme {
--color-tpt16-bg: #fafafa;
--color-tpt16-bg: oklch(0.985 0 0);
--color-tpt16-ink: #191919;
--color-tpt16-ink: oklch(0.21 0 0);
--color-tpt16-body: #474747;
--color-tpt16-body: oklch(0.42 0 0);
--color-tpt16-mut: #6b6b6b;
--color-tpt16-mut: oklch(0.53 0 0);
--color-tpt16-line: #e8e8e8;
--color-tpt16-line: oklch(0.93 0 0);
--color-tpt16-c1: #e8338a;
--color-tpt16-c1: oklch(0.62 0.23 355);
--color-tpt16-c2: #6a3fe0;
--color-tpt16-c2: oklch(0.53 0.22 285);
--color-tpt16-c3: #19b3d6;
--color-tpt16-c3: oklch(0.71 0.13 215);
--color-tpt16-c3-ink: #0f7f9c;
--color-tpt16-c3-ink: oklch(0.55 0.1 220);
--font-tpt16-sans: 'Space Grotesk', system-ui, sans-serif;
--font-tpt16-mono: 'JetBrains Mono', ui-monospace, monospace;
}
/* Root rule: the full-bleed contract, stated in CSS as well as in the markup's utilities. */
.tpt-16 {
width: 100%;
min-height: 100svh;
}
/* Registered so the arc length can transition. */
@property --tpt16-p {
syntax: '<percentage>';
initial-value: 0%;
inherits: false;
}
```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 Pricing Card with Animated Gradient Border on Hover
Source: https://codefronts.com/components/tailwind-css-pricing-tables/tailwind-pricing-card-animated-gradient-border-hover/
Hover a clean minimal card and a pink-to-violet-to-cyan border draws itself clockwise from twelve o'clock, then un-draws when you leave. The border is one arbitrary [background:…] utility using the padding-box / border-box trick; its visible arc length is a registered @property percentage, transitioned by hover:[--tpt16-p:100%].
## HTML
```html
<section class="tpt-16 w-full min-h-svh grid place-items-center bg-tpt16-bg px-5 py-16 font-tpt16-sans text-tpt16-ink antialiased" aria-label="Pricing cards with gradient border draw effect">
<div class="grid w-full max-w-5xl justify-items-center gap-10">
<h2 class="text-center text-[clamp(26px,3.8vw,40px)] font-bold tracking-[-0.03em]">Sketch it. Ship it.</h2>
<div class="grid w-full gap-5 md:grid-cols-3">
<article class="flex flex-col gap-1.5 rounded-[20px] border-2 border-transparent p-8 [background:linear-gradient(white,white)_padding-box,conic-gradient(from_-90deg,var(--color-tpt16-c1),var(--color-tpt16-c2)_calc(var(--tpt16-p)*.5),var(--color-tpt16-c3)_var(--tpt16-p),var(--color-tpt16-line)_0)_border-box] [transition:--tpt16-p_800ms_cubic-bezier(.5,0,.2,1),box-shadow_350ms] hover:shadow-[0_20px_44px_-28px_var(--color-tpt16-c2)] hover:[--tpt16-p:100%] focus-within:[--tpt16-p:100%] motion-reduce:[transition:none]">
<h3 class="text-[13px] font-semibold tracking-[0.08em] text-tpt16-mut uppercase">Sketch</h3>
<p class="text-[44px] leading-tight font-bold tracking-[-0.035em]">$11<small class="text-[15px] font-medium tracking-normal text-tpt16-mut">/mo</small></p>
<ul class="mt-3 mb-6 grid flex-1 content-start gap-2.5 text-sm text-tpt16-body *:flex *:gap-2.5 *:before:text-tpt16-c2 *:before:content-['→']"><li>3 boards</li><li>PNG export</li><li>Version history</li></ul>
<a href="#" class="grid min-h-11 place-items-center rounded-xl bg-tpt16-ink text-sm font-semibold text-white no-underline transition hover:bg-linear-to-r hover:from-tpt16-c1 hover:via-tpt16-c2 hover:to-tpt16-c3-ink focus-visible:outline-3 focus-visible:outline-offset-2 focus-visible:outline-tpt16-c2">Start Sketch</a>
</article>
<article class="relative flex flex-col gap-1.5 rounded-[20px] border-2 border-transparent p-8 [--tpt16-p:22%] [background:linear-gradient(white,white)_padding-box,conic-gradient(from_-90deg,var(--color-tpt16-c1),var(--color-tpt16-c2)_calc(var(--tpt16-p)*.5),var(--color-tpt16-c3)_var(--tpt16-p),var(--color-tpt16-line)_0)_border-box] [transition:--tpt16-p_800ms_cubic-bezier(.5,0,.2,1),box-shadow_350ms] hover:shadow-[0_20px_44px_-28px_var(--color-tpt16-c2)] hover:[--tpt16-p:100%] focus-within:[--tpt16-p:100%] motion-reduce:[transition:none]">
<span class="absolute -top-3 left-8 rounded-full bg-linear-to-r from-tpt16-c1 to-tpt16-c2 px-3 py-1 text-[10.5px] font-bold tracking-[0.08em] text-white uppercase">Most popular</span>
<h3 class="text-[13px] font-semibold tracking-[0.08em] text-tpt16-c2 uppercase">Draft</h3>
<p class="text-[44px] leading-tight font-bold tracking-[-0.035em]">$27<small class="text-[15px] font-medium tracking-normal text-tpt16-mut">/mo</small></p>
<ul class="mt-3 mb-6 grid flex-1 content-start gap-2.5 text-sm text-tpt16-body *:flex *:gap-2.5 *:before:text-tpt16-c2 *:before:content-['→']"><li>Unlimited boards</li><li>SVG + PDF export</li><li>Comments & mentions</li></ul>
<a href="#" class="grid min-h-11 place-items-center rounded-xl bg-tpt16-ink text-sm font-semibold text-white no-underline transition hover:bg-linear-to-r hover:from-tpt16-c1 hover:via-tpt16-c2 hover:to-tpt16-c3-ink focus-visible:outline-3 focus-visible:outline-offset-2 focus-visible:outline-tpt16-c2">Start Draft</a>
</article>
<article class="flex flex-col gap-1.5 rounded-[20px] border-2 border-transparent p-8 [background:linear-gradient(white,white)_padding-box,conic-gradient(from_-90deg,var(--color-tpt16-c1),var(--color-tpt16-c2)_calc(var(--tpt16-p)*.5),var(--color-tpt16-c3)_var(--tpt16-p),var(--color-tpt16-line)_0)_border-box] [transition:--tpt16-p_800ms_cubic-bezier(.5,0,.2,1),box-shadow_350ms] hover:shadow-[0_20px_44px_-28px_var(--color-tpt16-c2)] hover:[--tpt16-p:100%] focus-within:[--tpt16-p:100%] motion-reduce:[transition:none]">
<h3 class="text-[13px] font-semibold tracking-[0.08em] text-tpt16-mut uppercase">Studio</h3>
<p class="text-[44px] leading-tight font-bold tracking-[-0.035em]">$68<small class="text-[15px] font-medium tracking-normal text-tpt16-mut">/mo</small></p>
<ul class="mt-3 mb-6 grid flex-1 content-start gap-2.5 text-sm text-tpt16-body *:flex *:gap-2.5 *:before:text-tpt16-c2 *:before:content-['→']"><li>Everything in Draft</li><li>Team libraries</li><li>SSO</li></ul>
<a href="#" class="grid min-h-11 place-items-center rounded-xl bg-tpt16-ink text-sm font-semibold text-white no-underline transition hover:bg-linear-to-r hover:from-tpt16-c1 hover:via-tpt16-c2 hover:to-tpt16-c3-ink focus-visible:outline-3 focus-visible:outline-offset-2 focus-visible:outline-tpt16-c2">Start Studio</a>
</article>
</div>
<p aria-hidden="true" class="rounded-full border border-tpt16-line bg-white px-3.5 py-2 font-tpt16-mono text-[11.5px] text-tpt16-mut">@property --tpt16-p · hover:[--tpt16-p:100%] · padding-box / border-box</p>
</div>
</section>
```
## CSS
```css
@import "tailwindcss";
@theme {
--color-tpt16-bg: #fafafa;
--color-tpt16-bg: oklch(0.985 0 0);
--color-tpt16-ink: #191919;
--color-tpt16-ink: oklch(0.21 0 0);
--color-tpt16-body: #474747;
--color-tpt16-body: oklch(0.42 0 0);
--color-tpt16-mut: #6b6b6b;
--color-tpt16-mut: oklch(0.53 0 0);
--color-tpt16-line: #e8e8e8;
--color-tpt16-line: oklch(0.93 0 0);
--color-tpt16-c1: #e8338a;
--color-tpt16-c1: oklch(0.62 0.23 355);
--color-tpt16-c2: #6a3fe0;
--color-tpt16-c2: oklch(0.53 0.22 285);
--color-tpt16-c3: #19b3d6;
--color-tpt16-c3: oklch(0.71 0.13 215);
--color-tpt16-c3-ink: #0f7f9c;
--color-tpt16-c3-ink: oklch(0.55 0.1 220);
--font-tpt16-sans: 'Space Grotesk', system-ui, sans-serif;
--font-tpt16-mono: 'JetBrains Mono', ui-monospace, monospace;
}
/* Root rule: the full-bleed contract, stated in CSS as well as in the markup's utilities. */
.tpt-16 {
width: 100%;
min-height: 100svh;
}
/* Registered so the arc length can transition. */
@property --tpt16-p {
syntax: '<percentage>';
initial-value: 0%;
inherits: false;
}
```How this works
A transition, not an animation. Because the property is registered, the card can transition it like any length:
[transition:--tpt16-p_800ms_cubic-bezier(.5,0,.2,1)]
hover:[--tpt16-p:100%]Leaving the card reverses the draw naturally, from wherever it had reached.
No mask needed. The CSS original drew the ring on a masked ::before with a -webkit-mask-composite twin. The padding-box / border-box pair paints it on the card itself: the solid padding-box layer covers the inside, the gradient shows only through the transparent 2px border, and the part beyond --tpt16-p is the neutral line colour.
Make it yours
- Draw speed:
800msin the arbitrary transition. - Start point:
from_-90deg(top);from_90degdraws from the bottom. - Palette: the three
--color-tpt16-c*tokens. - Persist on a selected card: add
[--tpt16-p:100%]at rest.
Gotchas — read before shipping
- Without
@propertythe percentage snaps; older engines show the full ring instantly on hover — acceptable degradation. - Transitioning a custom property needs the property named explicitly; the default
transitionlist doesn't include it. - Hard stops need the
0trick (line 0) — a repeated position would blend a sliver.
Browser support
| Chrome | Safari | Firefox | Edge |
|---|---|---|---|
| 111+ | 16.4+ | 128+ | 111+ |
@property gates the sweep; it matches Tailwind v4's own floor.