03 / 30
All 30 in 30 Tailwind CSS Text Hover Effects
- 01Tailwind CSS Animated Underline Hover Effect
- 02Tailwind Liquid Text Fill Hover Animation
- 03Tailwind Gradient Text Hover Effect with bg-clip-text
- 04Tailwind Animated Strikethrough Text Hover Effect
- 05Tailwind Text Swap and Flip Up Hover Effect
- 06Tailwind CSS Glitch Text Hover Effect
- 07Tailwind Neon Glow Text with Flicker Animation
- 08Tailwind Metallic Gold Shimmer Text Effect
- 09Tailwind 3D Text Pop and Lift Hover Effect
- 10Tailwind Staggered Letter Wave Hover Animation
- 11Tailwind Spotlight Text Reveal on Mouse Hover
- 12Tailwind Hover to Reveal Hidden Spoiler Text
- 13Tailwind Blur to Focus Text Hover Effect
- 14Tailwind Magnetic Hover Effect for Buttons and Text
- 15Tailwind Letter Spacing Expand on Hover (Tracking Animation)
- 16Tailwind Outline Text Stroke to Fill Hover Effect
- 17Tailwind Text Scramble and Matrix Decrypt Hover Effect
- 18Tailwind Animated Border Button Hover Effect
- 19Tailwind Elastic Rubber Band Text Hover Animation
- 20Tailwind Variable Font Weight Hover Animation
- 21Tailwind Animated Rainbow Gradient Text on Hover
- 22Tailwind 3D Perspective Tilt Text Hover Effect
- 23Tailwind Smoke Dissolve Text Hover Effect
- 24Tailwind Fire Text Effect with Heat Wave Glow
- 25Tailwind Dynamic Text Shadow that Follows the Cursor
- 26Tailwind Infinite Text Marquee that Speeds Up on Hover
- 27Tailwind Duotone Split Color Text Hover Effect
- 28Tailwind CSS Tooltip on Hover (No JavaScript)
- 29Tailwind SVG Water Ripple Distortion Text Effect
- 30Tailwind Clip-Path Text Reveal Hover Animation
Tailwind Gradient Text Hover Effect with bg-clip-text
Solid ink that crossfades into a live gradient: the gradient is always painted behind the glyphs with bg-clip-text, and hover just fades text-tth03-ink to text-transparent. Once revealed, a typed --tth03-angle keeps the gradient slowly turning. Each row sets its own two stops with a two-variable style.
Untitled UI Pro: 5,000+ React + Tailwind CSS v4 components · from $349 one-time
Untitled UI React · Affiliate link
The code
<section class="tth-03 @container w-full min-h-svh grid place-items-center bg-tth03-bg px-5 py-14 font-tth03-sans text-tth03-ink" aria-label="Gradient text color reveal demo">
<div class="flex w-full max-w-[52rem] flex-col gap-6">
<header class="flex flex-wrap items-center justify-between gap-3.5">
<p class="text-xs font-bold uppercase tracking-[0.24em] text-tth03-mut">Northlight platform — 2026.3</p>
<span class="rounded-full border border-tth03-line bg-white px-3 py-1.5 font-tth03-mono text-[11px] text-tth03-mut @max-[35rem]:hidden">text-ink → text-transparent over bg-clip-text</span>
</header>
<ol class="border-t-[1.5px] border-tth03-ink">
<li class="border-b border-tth03-line"><a id="tth03-top" href="#tth03-top" style="--tth03-from:oklch(0.68 0.21 25);--tth03-to:oklch(0.76 0.17 65)" class="flex items-baseline gap-[clamp(14px,3cqi,26px)] rounded-[3px] px-1 py-[clamp(14px,2.6cqi,22px)] text-[clamp(26px,5.4cqi,46px)] font-extrabold leading-[1.12] tracking-[-0.025em] no-underline bg-[linear-gradient(var(--tth03-angle),var(--tth03-from),var(--tth03-to))] bg-clip-text text-tth03-ink transition-[color,translate] duration-500 ease-[cubic-bezier(.22,1,.36,1)] hover:translate-x-1.5 hover:text-transparent hover:animate-tth03-turn focus-visible:text-transparent focus-visible:outline-2 focus-visible:outline-offset-4 focus-visible:outline-tth03-ink motion-reduce:transition-none motion-reduce:animate-none!"><small class="font-tth03-mono text-xs font-semibold tracking-[0.08em] [-webkit-text-fill-color:var(--color-tth03-mut)]">001</small>Realtime ledger sync</a></li>
<li class="border-b border-tth03-line"><a href="#tth03-top" style="--tth03-from:oklch(0.7 0.17 150);--tth03-to:oklch(0.74 0.14 210)" class="flex items-baseline gap-[clamp(14px,3cqi,26px)] rounded-[3px] px-1 py-[clamp(14px,2.6cqi,22px)] text-[clamp(26px,5.4cqi,46px)] font-extrabold leading-[1.12] tracking-[-0.025em] no-underline bg-[linear-gradient(var(--tth03-angle),var(--tth03-from),var(--tth03-to))] bg-clip-text text-tth03-ink transition-[color,translate] duration-500 ease-[cubic-bezier(.22,1,.36,1)] hover:translate-x-1.5 hover:text-transparent hover:animate-tth03-turn focus-visible:text-transparent focus-visible:outline-2 focus-visible:outline-offset-4 focus-visible:outline-tth03-ink motion-reduce:transition-none motion-reduce:animate-none!"><small class="font-tth03-mono text-xs font-semibold tracking-[0.08em] [-webkit-text-fill-color:var(--color-tth03-mut)]">002</small>Anomaly-aware alerts</a></li>
<li class="border-b border-tth03-line"><a href="#tth03-top" style="--tth03-from:oklch(0.6 0.22 300);--tth03-to:oklch(0.68 0.2 345)" class="flex items-baseline gap-[clamp(14px,3cqi,26px)] rounded-[3px] px-1 py-[clamp(14px,2.6cqi,22px)] text-[clamp(26px,5.4cqi,46px)] font-extrabold leading-[1.12] tracking-[-0.025em] no-underline bg-[linear-gradient(var(--tth03-angle),var(--tth03-from),var(--tth03-to))] bg-clip-text text-tth03-ink transition-[color,translate] duration-500 ease-[cubic-bezier(.22,1,.36,1)] hover:translate-x-1.5 hover:text-transparent hover:animate-tth03-turn focus-visible:text-transparent focus-visible:outline-2 focus-visible:outline-offset-4 focus-visible:outline-tth03-ink motion-reduce:transition-none motion-reduce:animate-none!"><small class="font-tth03-mono text-xs font-semibold tracking-[0.08em] [-webkit-text-fill-color:var(--color-tth03-mut)]">003</small>Zero-copy exports</a></li>
<li class="border-b border-tth03-line"><a href="#tth03-top" style="--tth03-from:oklch(0.62 0.18 255);--tth03-to:oklch(0.74 0.14 195)" class="flex items-baseline gap-[clamp(14px,3cqi,26px)] rounded-[3px] px-1 py-[clamp(14px,2.6cqi,22px)] text-[clamp(26px,5.4cqi,46px)] font-extrabold leading-[1.12] tracking-[-0.025em] no-underline bg-[linear-gradient(var(--tth03-angle),var(--tth03-from),var(--tth03-to))] bg-clip-text text-tth03-ink transition-[color,translate] duration-500 ease-[cubic-bezier(.22,1,.36,1)] hover:translate-x-1.5 hover:text-transparent hover:animate-tth03-turn focus-visible:text-transparent focus-visible:outline-2 focus-visible:outline-offset-4 focus-visible:outline-tth03-ink motion-reduce:transition-none motion-reduce:animate-none!"><small class="font-tth03-mono text-xs font-semibold tracking-[0.08em] [-webkit-text-fill-color:var(--color-tth03-mut)]">004</small>Region-pinned vaults</a></li>
</ol>
<p class="text-[12.5px] text-tth03-mut">Hover or <kbd class="rounded-[5px] border border-b-2 border-tth03-line bg-white px-1.5 py-0.5 font-tth03-mono text-[11px]">Tab</kbd>: solid ink crossfades to a live gradient — and the gradient keeps slowly turning while you stay.</p>
</div>
</section><section class="tth-03 @container w-full min-h-svh grid place-items-center bg-tth03-bg px-5 py-14 font-tth03-sans text-tth03-ink" aria-label="Gradient text color reveal demo">
<div class="flex w-full max-w-[52rem] flex-col gap-6">
<header class="flex flex-wrap items-center justify-between gap-3.5">
<p class="text-xs font-bold uppercase tracking-[0.24em] text-tth03-mut">Northlight platform — 2026.3</p>
<span class="rounded-full border border-tth03-line bg-white px-3 py-1.5 font-tth03-mono text-[11px] text-tth03-mut @max-[35rem]:hidden">text-ink → text-transparent over bg-clip-text</span>
</header>
<ol class="border-t-[1.5px] border-tth03-ink">
<li class="border-b border-tth03-line"><a id="tth03-top" href="#tth03-top" style="--tth03-from:oklch(0.68 0.21 25);--tth03-to:oklch(0.76 0.17 65)" class="flex items-baseline gap-[clamp(14px,3cqi,26px)] rounded-[3px] px-1 py-[clamp(14px,2.6cqi,22px)] text-[clamp(26px,5.4cqi,46px)] font-extrabold leading-[1.12] tracking-[-0.025em] no-underline bg-[linear-gradient(var(--tth03-angle),var(--tth03-from),var(--tth03-to))] bg-clip-text text-tth03-ink transition-[color,translate] duration-500 ease-[cubic-bezier(.22,1,.36,1)] hover:translate-x-1.5 hover:text-transparent hover:animate-tth03-turn focus-visible:text-transparent focus-visible:outline-2 focus-visible:outline-offset-4 focus-visible:outline-tth03-ink motion-reduce:transition-none motion-reduce:animate-none!"><small class="font-tth03-mono text-xs font-semibold tracking-[0.08em] [-webkit-text-fill-color:var(--color-tth03-mut)]">001</small>Realtime ledger sync</a></li>
<li class="border-b border-tth03-line"><a href="#tth03-top" style="--tth03-from:oklch(0.7 0.17 150);--tth03-to:oklch(0.74 0.14 210)" class="flex items-baseline gap-[clamp(14px,3cqi,26px)] rounded-[3px] px-1 py-[clamp(14px,2.6cqi,22px)] text-[clamp(26px,5.4cqi,46px)] font-extrabold leading-[1.12] tracking-[-0.025em] no-underline bg-[linear-gradient(var(--tth03-angle),var(--tth03-from),var(--tth03-to))] bg-clip-text text-tth03-ink transition-[color,translate] duration-500 ease-[cubic-bezier(.22,1,.36,1)] hover:translate-x-1.5 hover:text-transparent hover:animate-tth03-turn focus-visible:text-transparent focus-visible:outline-2 focus-visible:outline-offset-4 focus-visible:outline-tth03-ink motion-reduce:transition-none motion-reduce:animate-none!"><small class="font-tth03-mono text-xs font-semibold tracking-[0.08em] [-webkit-text-fill-color:var(--color-tth03-mut)]">002</small>Anomaly-aware alerts</a></li>
<li class="border-b border-tth03-line"><a href="#tth03-top" style="--tth03-from:oklch(0.6 0.22 300);--tth03-to:oklch(0.68 0.2 345)" class="flex items-baseline gap-[clamp(14px,3cqi,26px)] rounded-[3px] px-1 py-[clamp(14px,2.6cqi,22px)] text-[clamp(26px,5.4cqi,46px)] font-extrabold leading-[1.12] tracking-[-0.025em] no-underline bg-[linear-gradient(var(--tth03-angle),var(--tth03-from),var(--tth03-to))] bg-clip-text text-tth03-ink transition-[color,translate] duration-500 ease-[cubic-bezier(.22,1,.36,1)] hover:translate-x-1.5 hover:text-transparent hover:animate-tth03-turn focus-visible:text-transparent focus-visible:outline-2 focus-visible:outline-offset-4 focus-visible:outline-tth03-ink motion-reduce:transition-none motion-reduce:animate-none!"><small class="font-tth03-mono text-xs font-semibold tracking-[0.08em] [-webkit-text-fill-color:var(--color-tth03-mut)]">003</small>Zero-copy exports</a></li>
<li class="border-b border-tth03-line"><a href="#tth03-top" style="--tth03-from:oklch(0.62 0.18 255);--tth03-to:oklch(0.74 0.14 195)" class="flex items-baseline gap-[clamp(14px,3cqi,26px)] rounded-[3px] px-1 py-[clamp(14px,2.6cqi,22px)] text-[clamp(26px,5.4cqi,46px)] font-extrabold leading-[1.12] tracking-[-0.025em] no-underline bg-[linear-gradient(var(--tth03-angle),var(--tth03-from),var(--tth03-to))] bg-clip-text text-tth03-ink transition-[color,translate] duration-500 ease-[cubic-bezier(.22,1,.36,1)] hover:translate-x-1.5 hover:text-transparent hover:animate-tth03-turn focus-visible:text-transparent focus-visible:outline-2 focus-visible:outline-offset-4 focus-visible:outline-tth03-ink motion-reduce:transition-none motion-reduce:animate-none!"><small class="font-tth03-mono text-xs font-semibold tracking-[0.08em] [-webkit-text-fill-color:var(--color-tth03-mut)]">004</small>Region-pinned vaults</a></li>
</ol>
<p class="text-[12.5px] text-tth03-mut">Hover or <kbd class="rounded-[5px] border border-b-2 border-tth03-line bg-white px-1.5 py-0.5 font-tth03-mono text-[11px]">Tab</kbd>: solid ink crossfades to a live gradient — and the gradient keeps slowly turning while you stay.</p>
</div>
</section>@import "tailwindcss";
@property --tth03-angle {
syntax: '<angle>';
inherits: false;
initial-value: 100deg;
}
@theme {
--color-tth03-bg: #f4f5f8;
--color-tth03-bg: oklch(0.965 0.005 250);
--color-tth03-ink: #1c1f27;
--color-tth03-ink: oklch(0.24 0.015 260);
--color-tth03-mut: #5e636e;
--color-tth03-mut: oklch(0.49 0.015 255);
--color-tth03-line: #dcdee4;
--color-tth03-line: oklch(0.89 0.008 250);
--font-tth03-sans: 'Geist', system-ui, sans-serif;
--font-tth03-mono: 'Geist Mono', ui-monospace, monospace;
--animate-tth03-turn: tth03-turn 4s ease-in-out 0.5s infinite alternate;
@keyframes tth03-turn {
from {
--tth03-angle: 100deg;
}
to {
--tth03-angle: 220deg;
}
}
}
.tth-03 {
width: 100%;
min-height: 100svh;
}@import "tailwindcss";
@property --tth03-angle {
syntax: '<angle>';
inherits: false;
initial-value: 100deg;
}
@theme {
--color-tth03-bg: #f4f5f8;
--color-tth03-bg: oklch(0.965 0.005 250);
--color-tth03-ink: #1c1f27;
--color-tth03-ink: oklch(0.24 0.015 260);
--color-tth03-mut: #5e636e;
--color-tth03-mut: oklch(0.49 0.015 255);
--color-tth03-line: #dcdee4;
--color-tth03-line: oklch(0.89 0.008 250);
--font-tth03-sans: 'Geist', system-ui, sans-serif;
--font-tth03-mono: 'Geist Mono', ui-monospace, monospace;
--animate-tth03-turn: tth03-turn 4s ease-in-out 0.5s infinite alternate;
@keyframes tth03-turn {
from {
--tth03-angle: 100deg;
}
to {
--tth03-angle: 220deg;
}
}
}
.tth-03 {
width: 100%;
min-height: 100svh;
}Setup — do this once per project
Skip this if your project already runs Tailwind v4.
<script src="https://cdn.jsdelivr.net/npm/@tailwindcss/browser@4"></script>
<script src="https://cdn.jsdelivr.net/npm/@tailwindcss/browser@4"></script>Compiles in the browser — perfect for a CodePen or a quick test, not for production.
npm install tailwindcss @tailwindcss/vite
npm install tailwindcss @tailwindcss/vite// vite.config.js ("type": "module" in package.json)
import { defineConfig } from 'vite'
import tailwindcss from '@tailwindcss/vite'
export default defineConfig({
plugins: [tailwindcss()],
})// vite.config.js ("type": "module" in package.json)
import { defineConfig } from 'vite'
import tailwindcss from '@tailwindcss/vite'
export default defineConfig({
plugins: [tailwindcss()],
})Any v4 setup works — Vite, PostCSS or the CLI. Nothing in this demo is bundler-specific.
@import "tailwindcss";
@property --tth03-angle {
syntax: '<angle>';
inherits: false;
initial-value: 100deg;
}
@theme {
--color-tth03-bg: #f4f5f8;
--color-tth03-bg: oklch(0.965 0.005 250);
--color-tth03-ink: #1c1f27;
--color-tth03-ink: oklch(0.24 0.015 260);
--color-tth03-mut: #5e636e;
--color-tth03-mut: oklch(0.49 0.015 255);
--color-tth03-line: #dcdee4;
--color-tth03-line: oklch(0.89 0.008 250);
--font-tth03-sans: 'Geist', system-ui, sans-serif;
--font-tth03-mono: 'Geist Mono', ui-monospace, monospace;
--animate-tth03-turn: tth03-turn 4s ease-in-out 0.5s infinite alternate;
@keyframes tth03-turn {
from {
--tth03-angle: 100deg;
}
to {
--tth03-angle: 220deg;
}
}
}
.tth-03 {
width: 100%;
min-height: 100svh;
}@import "tailwindcss";
@property --tth03-angle {
syntax: '<angle>';
inherits: false;
initial-value: 100deg;
}
@theme {
--color-tth03-bg: #f4f5f8;
--color-tth03-bg: oklch(0.965 0.005 250);
--color-tth03-ink: #1c1f27;
--color-tth03-ink: oklch(0.24 0.015 260);
--color-tth03-mut: #5e636e;
--color-tth03-mut: oklch(0.49 0.015 255);
--color-tth03-line: #dcdee4;
--color-tth03-line: oklch(0.89 0.008 250);
--font-tth03-sans: 'Geist', system-ui, sans-serif;
--font-tth03-mono: 'Geist Mono', ui-monospace, monospace;
--animate-tth03-turn: tth03-turn 4s ease-in-out 0.5s infinite alternate;
@keyframes tth03-turn {
from {
--tth03-angle: 100deg;
}
to {
--tth03-angle: 220deg;
}
}
}
.tth-03 {
width: 100%;
min-height: 100svh;
}<link rel="preconnect" href="https://fonts.googleapis.com"> <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin> <link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Geist:wght@400..900&family=Geist+Mono:wght@400;600&display=swap">
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Geist:wght@400..900&family=Geist+Mono:wght@400;600&display=swap">What changed in the port
Which parts became utilities, which stayed CSS, and why.
- The six-declaration
.cth-03__itemrule plus its hover rule collapsed into one class list per row; the@propertyangle is the only CSS beyond tokens. --from/--towere renamed--tth03-from/--tth03-toso the inline styles can't collide with another demo on the same page.- UI upgrade from the CSS original: gradient stops were darkened ~0.04 L so the revealed words keep ≥3:1 against the pale stage (they were washing out at the light end), and Geist replaced the system stack.
- UI upgrade: focus-visible now reveals the gradient as well as drawing the ring, so keyboard users see the same effect, not just an outline.
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 Text Hover Effect with bg-clip-text
Source: https://codefronts.com/motion/tailwind-css-text-hover-effects/tailwind-gradient-text-hover-effect-bg-clip-text/
Solid ink that crossfades into a live gradient: the gradient is always painted behind the glyphs with bg-clip-text, and hover just fades text-tth03-ink to text-transparent. Once revealed, a typed --tth03-angle keeps the gradient slowly turning. Each row sets its own two stops with a two-variable style.
## HTML
```html
<section class="tth-03 @container w-full min-h-svh grid place-items-center bg-tth03-bg px-5 py-14 font-tth03-sans text-tth03-ink" aria-label="Gradient text color reveal demo">
<div class="flex w-full max-w-[52rem] flex-col gap-6">
<header class="flex flex-wrap items-center justify-between gap-3.5">
<p class="text-xs font-bold uppercase tracking-[0.24em] text-tth03-mut">Northlight platform — 2026.3</p>
<span class="rounded-full border border-tth03-line bg-white px-3 py-1.5 font-tth03-mono text-[11px] text-tth03-mut @max-[35rem]:hidden">text-ink → text-transparent over bg-clip-text</span>
</header>
<ol class="border-t-[1.5px] border-tth03-ink">
<li class="border-b border-tth03-line"><a id="tth03-top" href="#tth03-top" style="--tth03-from:oklch(0.68 0.21 25);--tth03-to:oklch(0.76 0.17 65)" class="flex items-baseline gap-[clamp(14px,3cqi,26px)] rounded-[3px] px-1 py-[clamp(14px,2.6cqi,22px)] text-[clamp(26px,5.4cqi,46px)] font-extrabold leading-[1.12] tracking-[-0.025em] no-underline bg-[linear-gradient(var(--tth03-angle),var(--tth03-from),var(--tth03-to))] bg-clip-text text-tth03-ink transition-[color,translate] duration-500 ease-[cubic-bezier(.22,1,.36,1)] hover:translate-x-1.5 hover:text-transparent hover:animate-tth03-turn focus-visible:text-transparent focus-visible:outline-2 focus-visible:outline-offset-4 focus-visible:outline-tth03-ink motion-reduce:transition-none motion-reduce:animate-none!"><small class="font-tth03-mono text-xs font-semibold tracking-[0.08em] [-webkit-text-fill-color:var(--color-tth03-mut)]">001</small>Realtime ledger sync</a></li>
<li class="border-b border-tth03-line"><a href="#tth03-top" style="--tth03-from:oklch(0.7 0.17 150);--tth03-to:oklch(0.74 0.14 210)" class="flex items-baseline gap-[clamp(14px,3cqi,26px)] rounded-[3px] px-1 py-[clamp(14px,2.6cqi,22px)] text-[clamp(26px,5.4cqi,46px)] font-extrabold leading-[1.12] tracking-[-0.025em] no-underline bg-[linear-gradient(var(--tth03-angle),var(--tth03-from),var(--tth03-to))] bg-clip-text text-tth03-ink transition-[color,translate] duration-500 ease-[cubic-bezier(.22,1,.36,1)] hover:translate-x-1.5 hover:text-transparent hover:animate-tth03-turn focus-visible:text-transparent focus-visible:outline-2 focus-visible:outline-offset-4 focus-visible:outline-tth03-ink motion-reduce:transition-none motion-reduce:animate-none!"><small class="font-tth03-mono text-xs font-semibold tracking-[0.08em] [-webkit-text-fill-color:var(--color-tth03-mut)]">002</small>Anomaly-aware alerts</a></li>
<li class="border-b border-tth03-line"><a href="#tth03-top" style="--tth03-from:oklch(0.6 0.22 300);--tth03-to:oklch(0.68 0.2 345)" class="flex items-baseline gap-[clamp(14px,3cqi,26px)] rounded-[3px] px-1 py-[clamp(14px,2.6cqi,22px)] text-[clamp(26px,5.4cqi,46px)] font-extrabold leading-[1.12] tracking-[-0.025em] no-underline bg-[linear-gradient(var(--tth03-angle),var(--tth03-from),var(--tth03-to))] bg-clip-text text-tth03-ink transition-[color,translate] duration-500 ease-[cubic-bezier(.22,1,.36,1)] hover:translate-x-1.5 hover:text-transparent hover:animate-tth03-turn focus-visible:text-transparent focus-visible:outline-2 focus-visible:outline-offset-4 focus-visible:outline-tth03-ink motion-reduce:transition-none motion-reduce:animate-none!"><small class="font-tth03-mono text-xs font-semibold tracking-[0.08em] [-webkit-text-fill-color:var(--color-tth03-mut)]">003</small>Zero-copy exports</a></li>
<li class="border-b border-tth03-line"><a href="#tth03-top" style="--tth03-from:oklch(0.62 0.18 255);--tth03-to:oklch(0.74 0.14 195)" class="flex items-baseline gap-[clamp(14px,3cqi,26px)] rounded-[3px] px-1 py-[clamp(14px,2.6cqi,22px)] text-[clamp(26px,5.4cqi,46px)] font-extrabold leading-[1.12] tracking-[-0.025em] no-underline bg-[linear-gradient(var(--tth03-angle),var(--tth03-from),var(--tth03-to))] bg-clip-text text-tth03-ink transition-[color,translate] duration-500 ease-[cubic-bezier(.22,1,.36,1)] hover:translate-x-1.5 hover:text-transparent hover:animate-tth03-turn focus-visible:text-transparent focus-visible:outline-2 focus-visible:outline-offset-4 focus-visible:outline-tth03-ink motion-reduce:transition-none motion-reduce:animate-none!"><small class="font-tth03-mono text-xs font-semibold tracking-[0.08em] [-webkit-text-fill-color:var(--color-tth03-mut)]">004</small>Region-pinned vaults</a></li>
</ol>
<p class="text-[12.5px] text-tth03-mut">Hover or <kbd class="rounded-[5px] border border-b-2 border-tth03-line bg-white px-1.5 py-0.5 font-tth03-mono text-[11px]">Tab</kbd>: solid ink crossfades to a live gradient — and the gradient keeps slowly turning while you stay.</p>
</div>
</section>
```
## CSS
```css
@import "tailwindcss";
@property --tth03-angle {
syntax: '<angle>';
inherits: false;
initial-value: 100deg;
}
@theme {
--color-tth03-bg: #f4f5f8;
--color-tth03-bg: oklch(0.965 0.005 250);
--color-tth03-ink: #1c1f27;
--color-tth03-ink: oklch(0.24 0.015 260);
--color-tth03-mut: #5e636e;
--color-tth03-mut: oklch(0.49 0.015 255);
--color-tth03-line: #dcdee4;
--color-tth03-line: oklch(0.89 0.008 250);
--font-tth03-sans: 'Geist', system-ui, sans-serif;
--font-tth03-mono: 'Geist Mono', ui-monospace, monospace;
--animate-tth03-turn: tth03-turn 4s ease-in-out 0.5s infinite alternate;
@keyframes tth03-turn {
from {
--tth03-angle: 100deg;
}
to {
--tth03-angle: 220deg;
}
}
}
.tth-03 {
width: 100%;
min-height: 100svh;
}
```Here's a working CSS demo from CodeFronts. Use it as-is or adapt to your framework. All classes are scoped under a unique prefix so the code won't collide with your existing styles. MIT licensed.
Demo: Tailwind Gradient Text Hover Effect with bg-clip-text
Source: https://codefronts.com/motion/tailwind-css-text-hover-effects/tailwind-gradient-text-hover-effect-bg-clip-text/
Solid ink that crossfades into a live gradient: the gradient is always painted behind the glyphs with bg-clip-text, and hover just fades text-tth03-ink to text-transparent. Once revealed, a typed --tth03-angle keeps the gradient slowly turning. Each row sets its own two stops with a two-variable style.
## HTML
```html
<section class="tth-03 @container w-full min-h-svh grid place-items-center bg-tth03-bg px-5 py-14 font-tth03-sans text-tth03-ink" aria-label="Gradient text color reveal demo">
<div class="flex w-full max-w-[52rem] flex-col gap-6">
<header class="flex flex-wrap items-center justify-between gap-3.5">
<p class="text-xs font-bold uppercase tracking-[0.24em] text-tth03-mut">Northlight platform — 2026.3</p>
<span class="rounded-full border border-tth03-line bg-white px-3 py-1.5 font-tth03-mono text-[11px] text-tth03-mut @max-[35rem]:hidden">text-ink → text-transparent over bg-clip-text</span>
</header>
<ol class="border-t-[1.5px] border-tth03-ink">
<li class="border-b border-tth03-line"><a id="tth03-top" href="#tth03-top" style="--tth03-from:oklch(0.68 0.21 25);--tth03-to:oklch(0.76 0.17 65)" class="flex items-baseline gap-[clamp(14px,3cqi,26px)] rounded-[3px] px-1 py-[clamp(14px,2.6cqi,22px)] text-[clamp(26px,5.4cqi,46px)] font-extrabold leading-[1.12] tracking-[-0.025em] no-underline bg-[linear-gradient(var(--tth03-angle),var(--tth03-from),var(--tth03-to))] bg-clip-text text-tth03-ink transition-[color,translate] duration-500 ease-[cubic-bezier(.22,1,.36,1)] hover:translate-x-1.5 hover:text-transparent hover:animate-tth03-turn focus-visible:text-transparent focus-visible:outline-2 focus-visible:outline-offset-4 focus-visible:outline-tth03-ink motion-reduce:transition-none motion-reduce:animate-none!"><small class="font-tth03-mono text-xs font-semibold tracking-[0.08em] [-webkit-text-fill-color:var(--color-tth03-mut)]">001</small>Realtime ledger sync</a></li>
<li class="border-b border-tth03-line"><a href="#tth03-top" style="--tth03-from:oklch(0.7 0.17 150);--tth03-to:oklch(0.74 0.14 210)" class="flex items-baseline gap-[clamp(14px,3cqi,26px)] rounded-[3px] px-1 py-[clamp(14px,2.6cqi,22px)] text-[clamp(26px,5.4cqi,46px)] font-extrabold leading-[1.12] tracking-[-0.025em] no-underline bg-[linear-gradient(var(--tth03-angle),var(--tth03-from),var(--tth03-to))] bg-clip-text text-tth03-ink transition-[color,translate] duration-500 ease-[cubic-bezier(.22,1,.36,1)] hover:translate-x-1.5 hover:text-transparent hover:animate-tth03-turn focus-visible:text-transparent focus-visible:outline-2 focus-visible:outline-offset-4 focus-visible:outline-tth03-ink motion-reduce:transition-none motion-reduce:animate-none!"><small class="font-tth03-mono text-xs font-semibold tracking-[0.08em] [-webkit-text-fill-color:var(--color-tth03-mut)]">002</small>Anomaly-aware alerts</a></li>
<li class="border-b border-tth03-line"><a href="#tth03-top" style="--tth03-from:oklch(0.6 0.22 300);--tth03-to:oklch(0.68 0.2 345)" class="flex items-baseline gap-[clamp(14px,3cqi,26px)] rounded-[3px] px-1 py-[clamp(14px,2.6cqi,22px)] text-[clamp(26px,5.4cqi,46px)] font-extrabold leading-[1.12] tracking-[-0.025em] no-underline bg-[linear-gradient(var(--tth03-angle),var(--tth03-from),var(--tth03-to))] bg-clip-text text-tth03-ink transition-[color,translate] duration-500 ease-[cubic-bezier(.22,1,.36,1)] hover:translate-x-1.5 hover:text-transparent hover:animate-tth03-turn focus-visible:text-transparent focus-visible:outline-2 focus-visible:outline-offset-4 focus-visible:outline-tth03-ink motion-reduce:transition-none motion-reduce:animate-none!"><small class="font-tth03-mono text-xs font-semibold tracking-[0.08em] [-webkit-text-fill-color:var(--color-tth03-mut)]">003</small>Zero-copy exports</a></li>
<li class="border-b border-tth03-line"><a href="#tth03-top" style="--tth03-from:oklch(0.62 0.18 255);--tth03-to:oklch(0.74 0.14 195)" class="flex items-baseline gap-[clamp(14px,3cqi,26px)] rounded-[3px] px-1 py-[clamp(14px,2.6cqi,22px)] text-[clamp(26px,5.4cqi,46px)] font-extrabold leading-[1.12] tracking-[-0.025em] no-underline bg-[linear-gradient(var(--tth03-angle),var(--tth03-from),var(--tth03-to))] bg-clip-text text-tth03-ink transition-[color,translate] duration-500 ease-[cubic-bezier(.22,1,.36,1)] hover:translate-x-1.5 hover:text-transparent hover:animate-tth03-turn focus-visible:text-transparent focus-visible:outline-2 focus-visible:outline-offset-4 focus-visible:outline-tth03-ink motion-reduce:transition-none motion-reduce:animate-none!"><small class="font-tth03-mono text-xs font-semibold tracking-[0.08em] [-webkit-text-fill-color:var(--color-tth03-mut)]">004</small>Region-pinned vaults</a></li>
</ol>
<p class="text-[12.5px] text-tth03-mut">Hover or <kbd class="rounded-[5px] border border-b-2 border-tth03-line bg-white px-1.5 py-0.5 font-tth03-mono text-[11px]">Tab</kbd>: solid ink crossfades to a live gradient — and the gradient keeps slowly turning while you stay.</p>
</div>
</section>
```
## CSS
```css
@import "tailwindcss";
@property --tth03-angle {
syntax: '<angle>';
inherits: false;
initial-value: 100deg;
}
@theme {
--color-tth03-bg: #f4f5f8;
--color-tth03-bg: oklch(0.965 0.005 250);
--color-tth03-ink: #1c1f27;
--color-tth03-ink: oklch(0.24 0.015 260);
--color-tth03-mut: #5e636e;
--color-tth03-mut: oklch(0.49 0.015 255);
--color-tth03-line: #dcdee4;
--color-tth03-line: oklch(0.89 0.008 250);
--font-tth03-sans: 'Geist', system-ui, sans-serif;
--font-tth03-mono: 'Geist Mono', ui-monospace, monospace;
--animate-tth03-turn: tth03-turn 4s ease-in-out 0.5s infinite alternate;
@keyframes tth03-turn {
from {
--tth03-angle: 100deg;
}
to {
--tth03-angle: 220deg;
}
}
}
.tth-03 {
width: 100%;
min-height: 100svh;
}
```How this works
Reveal by subtraction. You can't transition between a colour and a gradient, but you can transition a colour to transparent over a gradient that is already there:
<a class="bg-[linear-gradient(var(--tth03-angle),var(--tth03-from),var(--tth03-to))]
bg-clip-text text-tth03-ink transition-[color,translate] duration-500
hover:text-transparent hover:translate-x-1.5 hover:animate-tth03-turn">The turn. --tth03-angle is registered as an <angle>, so the keyframe in @theme can interpolate it from 100deg to 220deg and back. The animation only exists while hovered, and its 0.5s delay waits for the colour fade.
The numerals sit inside the same clipped link, so they'd turn transparent too. -webkit-text-fill-color overrides color for painting, pinning them to the muted token.
Make it yours
- New palette: change the two oklch stops in each row's
styleattribute. - Hue-rich blend: write the gradient as
linear-gradient(var(--tth03-angle)_in_oklch_longer_hue,…)for a rainbow arc between two stops. - Still gradient: drop
hover:animate-tth03-turnfor a calmer reveal.
Gotchas — read before shipping
- The link needs a solid
colorat rest —bg-clip-textonly shows where text is transparent. -webkit-text-fill-colorbeatscolor; never put it on the clipped element itself.- Descenders clip at the line box with tight leading; keep
leading-[1.12]or addpb-[0.08em].
Browser support
| Chrome | Safari | Firefox | Edge |
|---|---|---|---|
| 111+ | 16.4+ | 128+ | 111+ |
Unprefixed background-clip:text is universal in v4's floor; without @property the gradient shows but doesn't turn.