14 / 30
All 30 in 30 Tailwind CSS Login Forms
- 01Tailwind Split-Screen Brand Hero Login Form
- 02Tailwind Multi-Tenant Workspace Account Switcher
- 03Tailwind Floating Label Login Form with peer Variants
- 04Tailwind Web3 Wallet Connect Login Grid
- 05Tailwind Minimalist Fintech Login Card with Layered Shadow
- 06Tailwind OAuth Social Login Form with Brand SVG Buttons
- 07Tailwind Passwordless Magic Link Login with data-state Machine
- 08Tailwind Aurora Glow Login Card with Drifting Blur Blobs
- 09Tailwind Neon Synthwave Arcade Login Form
- 10Tailwind Sliding Login and Sign Up Panel with peer-checked
- 11Tailwind 3D Flip Login Card with Password Reset Back Face
- 12Tailwind Terminal CLI Prompt Login Form
- 13Tailwind Floating Pill Login Widget Docked Over App Content
- 14Tailwind Gradient Border Login Card with background-clip
- 15Tailwind Slide-Over Side Panel Login without JavaScript
- 16Tailwind Social-First Sign Up with Brand-Compliant Buttons
- 17Tailwind Animated Mascot Login that Covers Its Eyes
- 18Tailwind Accessible Compact Login Modal with Scale-In
- 19Tailwind Glassmorphism Login Card with backdrop-filter
- 20Tailwind Multi-Step Login Wizard with Radio-Driven Track
- 21Tailwind Animated Conic Gradient Border Login Card
- 22Tailwind Secure Vault Login with user-invalid Error State
- 23Tailwind Neo-Brutalist Login Form with Hard Offset Shadow
- 24Tailwind Show Hide Password Toggle with aria-pressed
- 25Tailwind OTP Code Input Grid with Auto-Advance
- 26Tailwind Password Strength Meter with data-score Variants
- 27Tailwind Numeric PIN Pad Login for Kiosks and POS
- 28Tailwind Inline Form Validation with user-valid and user-invalid
- 29Tailwind Particle Constellation Login over Canvas
- 30Tailwind Biometric Face ID Prompt with Pulse Ripples
Tailwind Gradient Border Login Card with background-clip
A dark-mode SaaS card wrapped in a fine multi-colour gradient hairline — one element, no nested wrapper, corners still round. The whole technique survives the port as a single arbitrary bg-[…] utility holding both background layers and their clips, which is either the best or the worst advertisement for arbitrary values depending on your taste.
Untitled UI Pro: 5,000+ React + Tailwind CSS v4 components · from $349 one-time
Untitled UI React · Affiliate link
The code
<section class="tlf-14 w-full min-h-svh grid place-items-center bg-tlf14-stage font-tlf14-sans p-6">
<form novalidate class="w-[min(380px,100%)] flex flex-col gap-3.5 p-8 rounded-[18px] border-[1.5px] border-transparent text-tlf14-ink bg-[linear-gradient(var(--color-tlf14-card),var(--color-tlf14-card))_padding-box,linear-gradient(135deg,oklch(0.7_0.2_20),oklch(0.7_0.18_300),oklch(0.75_0.16_200))_border-box] shadow-[0_30px_70px_-44px_black]">
<h1 class="text-[23px] font-bold tracking-tight">Sign in</h1>
<p class="-mt-2 mb-1 text-[13.5px] text-tlf14-mut">Access your dashboard.</p>
<label class="flex flex-col gap-1.5"><span class="text-[13px] font-semibold text-tlf14-label">Email</span>
<input type="email" autocomplete="email" placeholder="you@company.com" required class="h-12 px-3.5 rounded-xl text-[15px] text-tlf14-ink bg-tlf14-field border-[1.5px] border-tlf14-fieldedge transition-[border-color,box-shadow] duration-150 placeholder:text-tlf14-ph focus-visible:outline-none focus-visible:border-tlf14-acc focus-visible:ring-4 focus-visible:ring-tlf14-halo"></label>
<label class="flex flex-col gap-1.5"><span class="text-[13px] font-semibold text-tlf14-label">Password</span>
<input type="password" autocomplete="current-password" placeholder="••••••••" required class="h-12 px-3.5 rounded-xl text-[15px] text-tlf14-ink bg-tlf14-field border-[1.5px] border-tlf14-fieldedge transition-[border-color,box-shadow] duration-150 placeholder:text-tlf14-ph focus-visible:outline-none focus-visible:border-tlf14-acc focus-visible:ring-4 focus-visible:ring-tlf14-halo"></label>
<button type="submit" class="mt-1 h-12 rounded-xl border-0 cursor-pointer text-white text-[15px] font-semibold bg-[linear-gradient(135deg,oklch(0.62_0.2_20),oklch(0.58_0.18_300))] transition-[filter,scale] duration-150 hover:brightness-110 active:scale-[0.985] focus-visible:outline-3 focus-visible:outline-offset-3 focus-visible:outline-tlf14-ring motion-reduce:transition-none motion-reduce:active:scale-100">Continue</button>
<p class="text-center text-[13px] text-tlf14-mut">No account? <a href="#" class="font-semibold text-tlf14-link no-underline hover:underline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-tlf14-link">Start free</a></p>
</form>
</section><section class="tlf-14 w-full min-h-svh grid place-items-center bg-tlf14-stage font-tlf14-sans p-6">
<form novalidate class="w-[min(380px,100%)] flex flex-col gap-3.5 p-8 rounded-[18px] border-[1.5px] border-transparent text-tlf14-ink bg-[linear-gradient(var(--color-tlf14-card),var(--color-tlf14-card))_padding-box,linear-gradient(135deg,oklch(0.7_0.2_20),oklch(0.7_0.18_300),oklch(0.75_0.16_200))_border-box] shadow-[0_30px_70px_-44px_black]">
<h1 class="text-[23px] font-bold tracking-tight">Sign in</h1>
<p class="-mt-2 mb-1 text-[13.5px] text-tlf14-mut">Access your dashboard.</p>
<label class="flex flex-col gap-1.5"><span class="text-[13px] font-semibold text-tlf14-label">Email</span>
<input type="email" autocomplete="email" placeholder="you@company.com" required class="h-12 px-3.5 rounded-xl text-[15px] text-tlf14-ink bg-tlf14-field border-[1.5px] border-tlf14-fieldedge transition-[border-color,box-shadow] duration-150 placeholder:text-tlf14-ph focus-visible:outline-none focus-visible:border-tlf14-acc focus-visible:ring-4 focus-visible:ring-tlf14-halo"></label>
<label class="flex flex-col gap-1.5"><span class="text-[13px] font-semibold text-tlf14-label">Password</span>
<input type="password" autocomplete="current-password" placeholder="••••••••" required class="h-12 px-3.5 rounded-xl text-[15px] text-tlf14-ink bg-tlf14-field border-[1.5px] border-tlf14-fieldedge transition-[border-color,box-shadow] duration-150 placeholder:text-tlf14-ph focus-visible:outline-none focus-visible:border-tlf14-acc focus-visible:ring-4 focus-visible:ring-tlf14-halo"></label>
<button type="submit" class="mt-1 h-12 rounded-xl border-0 cursor-pointer text-white text-[15px] font-semibold bg-[linear-gradient(135deg,oklch(0.62_0.2_20),oklch(0.58_0.18_300))] transition-[filter,scale] duration-150 hover:brightness-110 active:scale-[0.985] focus-visible:outline-3 focus-visible:outline-offset-3 focus-visible:outline-tlf14-ring motion-reduce:transition-none motion-reduce:active:scale-100">Continue</button>
<p class="text-center text-[13px] text-tlf14-mut">No account? <a href="#" class="font-semibold text-tlf14-link no-underline hover:underline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-tlf14-link">Start free</a></p>
</form>
</section>@import "tailwindcss";
@theme {
--color-tlf14-stage: #0b0d13;
--color-tlf14-stage: oklch(0.15 0.013 270);
--color-tlf14-card: #151823;
--color-tlf14-card: oklch(0.2 0.015 270);
--color-tlf14-field: #101320;
--color-tlf14-field: oklch(0.18 0.015 270);
--color-tlf14-fieldedge: #2a2f3d;
--color-tlf14-fieldedge: oklch(0.3 0.018 270);
--color-tlf14-ink: #e9ecf5;
--color-tlf14-ink: oklch(0.94 0.008 270);
--color-tlf14-label: #c2c8d9;
--color-tlf14-label: oklch(0.84 0.014 270);
--color-tlf14-mut: #a0a7bb;
--color-tlf14-mut: oklch(0.72 0.018 270);
--color-tlf14-ph: #757d95;
--color-tlf14-ph: oklch(0.58 0.02 270);
--color-tlf14-acc: #b37cf0;
--color-tlf14-acc: oklch(0.7 0.18 300);
--color-tlf14-halo: #d4bcf6;
--color-tlf14-halo: oklch(0.7 0.18 300 / 0.22);
--color-tlf14-ring: #c7a8f4;
--color-tlf14-ring: oklch(0.7 0.18 300 / 0.6);
--color-tlf14-link: #f0a68f;
--color-tlf14-link: oklch(0.78 0.12 30);
--font-tlf14-sans: 'Space Grotesk', system-ui, sans-serif;
}
.tlf-14 {
width: 100%;
min-height: 100svh;
color-scheme: dark;
}@import "tailwindcss";
@theme {
--color-tlf14-stage: #0b0d13;
--color-tlf14-stage: oklch(0.15 0.013 270);
--color-tlf14-card: #151823;
--color-tlf14-card: oklch(0.2 0.015 270);
--color-tlf14-field: #101320;
--color-tlf14-field: oklch(0.18 0.015 270);
--color-tlf14-fieldedge: #2a2f3d;
--color-tlf14-fieldedge: oklch(0.3 0.018 270);
--color-tlf14-ink: #e9ecf5;
--color-tlf14-ink: oklch(0.94 0.008 270);
--color-tlf14-label: #c2c8d9;
--color-tlf14-label: oklch(0.84 0.014 270);
--color-tlf14-mut: #a0a7bb;
--color-tlf14-mut: oklch(0.72 0.018 270);
--color-tlf14-ph: #757d95;
--color-tlf14-ph: oklch(0.58 0.02 270);
--color-tlf14-acc: #b37cf0;
--color-tlf14-acc: oklch(0.7 0.18 300);
--color-tlf14-halo: #d4bcf6;
--color-tlf14-halo: oklch(0.7 0.18 300 / 0.22);
--color-tlf14-ring: #c7a8f4;
--color-tlf14-ring: oklch(0.7 0.18 300 / 0.6);
--color-tlf14-link: #f0a68f;
--color-tlf14-link: oklch(0.78 0.12 30);
--font-tlf14-sans: 'Space Grotesk', system-ui, sans-serif;
}
.tlf-14 {
width: 100%;
min-height: 100svh;
color-scheme: dark;
}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-tlf14-stage: #0b0d13;
--color-tlf14-stage: oklch(0.15 0.013 270);
--color-tlf14-card: #151823;
--color-tlf14-card: oklch(0.2 0.015 270);
--color-tlf14-field: #101320;
--color-tlf14-field: oklch(0.18 0.015 270);
--color-tlf14-fieldedge: #2a2f3d;
--color-tlf14-fieldedge: oklch(0.3 0.018 270);
--color-tlf14-ink: #e9ecf5;
--color-tlf14-ink: oklch(0.94 0.008 270);
--color-tlf14-label: #c2c8d9;
--color-tlf14-label: oklch(0.84 0.014 270);
--color-tlf14-mut: #a0a7bb;
--color-tlf14-mut: oklch(0.72 0.018 270);
--color-tlf14-ph: #757d95;
--color-tlf14-ph: oklch(0.58 0.02 270);
--color-tlf14-acc: #b37cf0;
--color-tlf14-acc: oklch(0.7 0.18 300);
--color-tlf14-halo: #d4bcf6;
--color-tlf14-halo: oklch(0.7 0.18 300 / 0.22);
--color-tlf14-ring: #c7a8f4;
--color-tlf14-ring: oklch(0.7 0.18 300 / 0.6);
--color-tlf14-link: #f0a68f;
--color-tlf14-link: oklch(0.78 0.12 30);
--font-tlf14-sans: 'Space Grotesk', system-ui, sans-serif;
}
.tlf-14 {
width: 100%;
min-height: 100svh;
color-scheme: dark;
}@import "tailwindcss";
@theme {
--color-tlf14-stage: #0b0d13;
--color-tlf14-stage: oklch(0.15 0.013 270);
--color-tlf14-card: #151823;
--color-tlf14-card: oklch(0.2 0.015 270);
--color-tlf14-field: #101320;
--color-tlf14-field: oklch(0.18 0.015 270);
--color-tlf14-fieldedge: #2a2f3d;
--color-tlf14-fieldedge: oklch(0.3 0.018 270);
--color-tlf14-ink: #e9ecf5;
--color-tlf14-ink: oklch(0.94 0.008 270);
--color-tlf14-label: #c2c8d9;
--color-tlf14-label: oklch(0.84 0.014 270);
--color-tlf14-mut: #a0a7bb;
--color-tlf14-mut: oklch(0.72 0.018 270);
--color-tlf14-ph: #757d95;
--color-tlf14-ph: oklch(0.58 0.02 270);
--color-tlf14-acc: #b37cf0;
--color-tlf14-acc: oklch(0.7 0.18 300);
--color-tlf14-halo: #d4bcf6;
--color-tlf14-halo: oklch(0.7 0.18 300 / 0.22);
--color-tlf14-ring: #c7a8f4;
--color-tlf14-ring: oklch(0.7 0.18 300 / 0.6);
--color-tlf14-link: #f0a68f;
--color-tlf14-link: oklch(0.78 0.12 30);
--font-tlf14-sans: 'Space Grotesk', system-ui, sans-serif;
}
.tlf-14 {
width: 100%;
min-height: 100svh;
color-scheme: dark;
}<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;500;600;700&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;500;600;700&display=swap">What changed in the port
Which parts became utilities, which stayed CSS, and why.
- This is the collection's longest single utility, and it is the right call anyway: the two layers and their clips are one indivisible value, and splitting them across utilities breaks the technique outright.
- Referencing
var(--color-tlf14-card)twice inside the arbitrary value means the inner surface is still retheme-able from@theme— arbitrary values and tokens are not mutually exclusive. - The gradient stops stay literal
oklch()rather than tokens, because a three-stop decorative frame is not a palette; promoting them to@themewould imply they are reusable brand colours. - UI change from the CSS original: Space Grotesk replaces the system stack, muted text lifted from
#8b92a6(4.2:1) tooklch(0.72 0.018 270)(7:1), the placeholder from#5f6780to0.58, and a sign-up line was added because a login card with no escape route is a dead end.
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 Gradient Border Login Card with background-clip
Source: https://codefronts.com/components/tailwind-css-login-forms/tailwind-gradient-border-login-card-background-clip/
A dark-mode SaaS card wrapped in a fine multi-colour gradient hairline — one element, no nested wrapper, corners still round. The whole technique survives the port as a single arbitrary bg-[…] utility holding both background layers and their clips, which is either the best or the worst advertisement for arbitrary values depending on your taste.
## HTML
```html
<section class="tlf-14 w-full min-h-svh grid place-items-center bg-tlf14-stage font-tlf14-sans p-6">
<form novalidate class="w-[min(380px,100%)] flex flex-col gap-3.5 p-8 rounded-[18px] border-[1.5px] border-transparent text-tlf14-ink bg-[linear-gradient(var(--color-tlf14-card),var(--color-tlf14-card))_padding-box,linear-gradient(135deg,oklch(0.7_0.2_20),oklch(0.7_0.18_300),oklch(0.75_0.16_200))_border-box] shadow-[0_30px_70px_-44px_black]">
<h1 class="text-[23px] font-bold tracking-tight">Sign in</h1>
<p class="-mt-2 mb-1 text-[13.5px] text-tlf14-mut">Access your dashboard.</p>
<label class="flex flex-col gap-1.5"><span class="text-[13px] font-semibold text-tlf14-label">Email</span>
<input type="email" autocomplete="email" placeholder="you@company.com" required class="h-12 px-3.5 rounded-xl text-[15px] text-tlf14-ink bg-tlf14-field border-[1.5px] border-tlf14-fieldedge transition-[border-color,box-shadow] duration-150 placeholder:text-tlf14-ph focus-visible:outline-none focus-visible:border-tlf14-acc focus-visible:ring-4 focus-visible:ring-tlf14-halo"></label>
<label class="flex flex-col gap-1.5"><span class="text-[13px] font-semibold text-tlf14-label">Password</span>
<input type="password" autocomplete="current-password" placeholder="••••••••" required class="h-12 px-3.5 rounded-xl text-[15px] text-tlf14-ink bg-tlf14-field border-[1.5px] border-tlf14-fieldedge transition-[border-color,box-shadow] duration-150 placeholder:text-tlf14-ph focus-visible:outline-none focus-visible:border-tlf14-acc focus-visible:ring-4 focus-visible:ring-tlf14-halo"></label>
<button type="submit" class="mt-1 h-12 rounded-xl border-0 cursor-pointer text-white text-[15px] font-semibold bg-[linear-gradient(135deg,oklch(0.62_0.2_20),oklch(0.58_0.18_300))] transition-[filter,scale] duration-150 hover:brightness-110 active:scale-[0.985] focus-visible:outline-3 focus-visible:outline-offset-3 focus-visible:outline-tlf14-ring motion-reduce:transition-none motion-reduce:active:scale-100">Continue</button>
<p class="text-center text-[13px] text-tlf14-mut">No account? <a href="#" class="font-semibold text-tlf14-link no-underline hover:underline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-tlf14-link">Start free</a></p>
</form>
</section>
```
## CSS
```css
@import "tailwindcss";
@theme {
--color-tlf14-stage: #0b0d13;
--color-tlf14-stage: oklch(0.15 0.013 270);
--color-tlf14-card: #151823;
--color-tlf14-card: oklch(0.2 0.015 270);
--color-tlf14-field: #101320;
--color-tlf14-field: oklch(0.18 0.015 270);
--color-tlf14-fieldedge: #2a2f3d;
--color-tlf14-fieldedge: oklch(0.3 0.018 270);
--color-tlf14-ink: #e9ecf5;
--color-tlf14-ink: oklch(0.94 0.008 270);
--color-tlf14-label: #c2c8d9;
--color-tlf14-label: oklch(0.84 0.014 270);
--color-tlf14-mut: #a0a7bb;
--color-tlf14-mut: oklch(0.72 0.018 270);
--color-tlf14-ph: #757d95;
--color-tlf14-ph: oklch(0.58 0.02 270);
--color-tlf14-acc: #b37cf0;
--color-tlf14-acc: oklch(0.7 0.18 300);
--color-tlf14-halo: #d4bcf6;
--color-tlf14-halo: oklch(0.7 0.18 300 / 0.22);
--color-tlf14-ring: #c7a8f4;
--color-tlf14-ring: oklch(0.7 0.18 300 / 0.6);
--color-tlf14-link: #f0a68f;
--color-tlf14-link: oklch(0.78 0.12 30);
--font-tlf14-sans: 'Space Grotesk', system-ui, sans-serif;
}
.tlf-14 {
width: 100%;
min-height: 100svh;
color-scheme: dark;
}
```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 Gradient Border Login Card with background-clip
Source: https://codefronts.com/components/tailwind-css-login-forms/tailwind-gradient-border-login-card-background-clip/
A dark-mode SaaS card wrapped in a fine multi-colour gradient hairline — one element, no nested wrapper, corners still round. The whole technique survives the port as a single arbitrary bg-[…] utility holding both background layers and their clips, which is either the best or the worst advertisement for arbitrary values depending on your taste.
## HTML
```html
<section class="tlf-14 w-full min-h-svh grid place-items-center bg-tlf14-stage font-tlf14-sans p-6">
<form novalidate class="w-[min(380px,100%)] flex flex-col gap-3.5 p-8 rounded-[18px] border-[1.5px] border-transparent text-tlf14-ink bg-[linear-gradient(var(--color-tlf14-card),var(--color-tlf14-card))_padding-box,linear-gradient(135deg,oklch(0.7_0.2_20),oklch(0.7_0.18_300),oklch(0.75_0.16_200))_border-box] shadow-[0_30px_70px_-44px_black]">
<h1 class="text-[23px] font-bold tracking-tight">Sign in</h1>
<p class="-mt-2 mb-1 text-[13.5px] text-tlf14-mut">Access your dashboard.</p>
<label class="flex flex-col gap-1.5"><span class="text-[13px] font-semibold text-tlf14-label">Email</span>
<input type="email" autocomplete="email" placeholder="you@company.com" required class="h-12 px-3.5 rounded-xl text-[15px] text-tlf14-ink bg-tlf14-field border-[1.5px] border-tlf14-fieldedge transition-[border-color,box-shadow] duration-150 placeholder:text-tlf14-ph focus-visible:outline-none focus-visible:border-tlf14-acc focus-visible:ring-4 focus-visible:ring-tlf14-halo"></label>
<label class="flex flex-col gap-1.5"><span class="text-[13px] font-semibold text-tlf14-label">Password</span>
<input type="password" autocomplete="current-password" placeholder="••••••••" required class="h-12 px-3.5 rounded-xl text-[15px] text-tlf14-ink bg-tlf14-field border-[1.5px] border-tlf14-fieldedge transition-[border-color,box-shadow] duration-150 placeholder:text-tlf14-ph focus-visible:outline-none focus-visible:border-tlf14-acc focus-visible:ring-4 focus-visible:ring-tlf14-halo"></label>
<button type="submit" class="mt-1 h-12 rounded-xl border-0 cursor-pointer text-white text-[15px] font-semibold bg-[linear-gradient(135deg,oklch(0.62_0.2_20),oklch(0.58_0.18_300))] transition-[filter,scale] duration-150 hover:brightness-110 active:scale-[0.985] focus-visible:outline-3 focus-visible:outline-offset-3 focus-visible:outline-tlf14-ring motion-reduce:transition-none motion-reduce:active:scale-100">Continue</button>
<p class="text-center text-[13px] text-tlf14-mut">No account? <a href="#" class="font-semibold text-tlf14-link no-underline hover:underline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-tlf14-link">Start free</a></p>
</form>
</section>
```
## CSS
```css
@import "tailwindcss";
@theme {
--color-tlf14-stage: #0b0d13;
--color-tlf14-stage: oklch(0.15 0.013 270);
--color-tlf14-card: #151823;
--color-tlf14-card: oklch(0.2 0.015 270);
--color-tlf14-field: #101320;
--color-tlf14-field: oklch(0.18 0.015 270);
--color-tlf14-fieldedge: #2a2f3d;
--color-tlf14-fieldedge: oklch(0.3 0.018 270);
--color-tlf14-ink: #e9ecf5;
--color-tlf14-ink: oklch(0.94 0.008 270);
--color-tlf14-label: #c2c8d9;
--color-tlf14-label: oklch(0.84 0.014 270);
--color-tlf14-mut: #a0a7bb;
--color-tlf14-mut: oklch(0.72 0.018 270);
--color-tlf14-ph: #757d95;
--color-tlf14-ph: oklch(0.58 0.02 270);
--color-tlf14-acc: #b37cf0;
--color-tlf14-acc: oklch(0.7 0.18 300);
--color-tlf14-halo: #d4bcf6;
--color-tlf14-halo: oklch(0.7 0.18 300 / 0.22);
--color-tlf14-ring: #c7a8f4;
--color-tlf14-ring: oklch(0.7 0.18 300 / 0.6);
--color-tlf14-link: #f0a68f;
--color-tlf14-link: oklch(0.78 0.12 30);
--font-tlf14-sans: 'Space Grotesk', system-ui, sans-serif;
}
.tlf-14 {
width: 100%;
min-height: 100svh;
color-scheme: dark;
}
```How this works
Why background-clip and not border-image. border-image cannot follow border-radius — the corners square off. Painting the gradient into the border box and a solid fill into the padding box keeps the radius intact, which is the only reason this technique is the standard one.
Layer order matters and the utility preserves it. The padding-box fill is declared first so it sits on top of the border-box gradient; reversing them hides the frame completely. Inside one bg-[…] value the order is explicit and adjacent, which is arguably clearer than two lines of a background shorthand.
The frame is decoration only. Field borders, text and focus halos all read their own tokens, so the card's contrast does not depend on where a gradient stop happens to land.
Make it yours
- Frame colours: the three stops in the
border-boxgradient. - Frame weight:
border-[1.5px]→border-2for a bolder edge. - Inner surface:
--color-tlf14-card(used twice in the padding-box layer). - Animate it: add
bg-[length:200%_200%]and a position keyframe for a slow shimmer — see demo 21 for the conic version.
Gotchas — read before shipping
- The border must be
transparentand non-zero. Aborder-0card has no border box to paint, and the frame silently disappears. - Keep both layers in ONE
bg-[…]utility. Two separate background utilities overwrite each other — last one wins, frame gone. - Underscore every space inside the value, including inside
linear-gradient()and aroundpadding-box/border-box.
Browser support
| Chrome | Safari | Firefox | Edge |
|---|---|---|---|
| 111+ | 16.4+ | 128+ | 111+ |
Per-layer background-clip is universally supported; the floor is Tailwind v4's generated sheet.