Pure TailwindMIT licensed

Tailwind Gradient Text Reveal Hover Effect

Six ways to paint a gradient onto letterforms on hover — position wipe, radial burst, rainbow shift, shimmer keyframe, duotone hue swap and a diagonal sweep. bg-clip-text and text-transparent are first-class utilities, which makes this the port that shrinks the most.

Live Demo
Plain CSSTailwind v4
Try it

Untitled UI Pro: 5,000+ React + Tailwind CSS v4 components · from $349 one-time

Untitled UI React · Affiliate link

Get Untitled UI Pro

The code

<section class="thv-04 w-full min-h-svh grid place-items-center bg-thv04-bg font-thv04-sans px-6 py-14">
  <div class="w-[min(900px,100%)] grid grid-cols-[repeat(auto-fit,minmax(230px,1fr))] gap-8">
    <div class="flex flex-col items-center gap-5 px-6 py-12 rounded-2xl bg-white/[0.025] border border-white/[0.07]">
      <span tabindex="0" class="inline-block text-[clamp(1.6rem,4vw,2.4rem)] font-black tracking-[0.06em] text-thv04-text bg-clip-text bg-[linear-gradient(90deg,#7c3aed,#06b6d4,#10b981)] [background-size:200%_auto] [background-position:right_center] rounded-xs transition-[background-position,color] duration-500 ease-[cubic-bezier(.4,0,.2,1)] hover:text-transparent hover:[background-position:left_center] focus-visible:text-transparent focus-visible:[background-position:left_center] focus-visible:outline-2 focus-visible:outline-offset-6 focus-visible:outline-thv04-ring motion-reduce:transition-none">AURORA</span>
      <span class="text-[10px] tracking-[0.15em] uppercase text-thv04-dim text-center">gradient position wipe</span>
    </div>
    <div class="flex flex-col items-center gap-5 px-6 py-12 rounded-2xl bg-white/[0.025] border border-white/[0.07]">
      <span tabindex="0" class="inline-block text-[clamp(1.6rem,4vw,2.4rem)] font-black tracking-[0.06em] text-thv04-text bg-clip-text bg-[radial-gradient(circle_at_50%_50%,#f59e0b,#ef4444,#7c3aed)] [background-size:0%_0%] [background-position:center] bg-no-repeat rounded-xs transition-[background-size,color] duration-500 ease-[cubic-bezier(.4,0,.2,1)] hover:text-transparent hover:[background-size:200%_200%] focus-visible:text-transparent focus-visible:[background-size:200%_200%] focus-visible:outline-2 focus-visible:outline-offset-6 focus-visible:outline-thv04-ring motion-reduce:transition-none">RADIAL</span>
      <span class="text-[10px] tracking-[0.15em] uppercase text-thv04-dim text-center">radial-gradient burst</span>
    </div>
    <div class="flex flex-col items-center gap-5 px-6 py-12 rounded-2xl bg-white/[0.025] border border-white/[0.07]">
      <span tabindex="0" class="inline-block text-[clamp(1.6rem,4vw,2.4rem)] font-black tracking-[0.06em] text-thv04-text bg-clip-text bg-[linear-gradient(90deg,#f43f5e,#f59e0b,#10b981,#06b6d4,#6d28d9,#f43f5e)] [background-size:400%_auto] [background-position:0%_center] rounded-xs transition-[background-position,color] duration-600 hover:text-transparent hover:[background-position:100%_center] focus-visible:text-transparent focus-visible:[background-position:100%_center] focus-visible:outline-2 focus-visible:outline-offset-6 focus-visible:outline-thv04-ring motion-reduce:transition-none">SPECTRUM</span>
      <span class="text-[10px] tracking-[0.15em] uppercase text-thv04-dim text-center">rainbow hue-shift</span>
    </div>
    <div class="flex flex-col items-center gap-5 px-6 py-12 rounded-2xl bg-white/[0.025] border border-white/[0.07]">
      <span tabindex="0" class="inline-block text-[clamp(1.6rem,4vw,2.4rem)] font-black tracking-[0.06em] text-thv04-text bg-clip-text bg-[linear-gradient(105deg,#c4b5fd_0%,#fff_40%,#7c3aed_55%,#c4b5fd_100%)] [background-size:200%_auto] rounded-xs transition-colors duration-300 hover:text-transparent hover:animate-thv04-shimmer focus-visible:text-transparent focus-visible:animate-thv04-shimmer focus-visible:outline-2 focus-visible:outline-offset-6 focus-visible:outline-thv04-ring motion-reduce:hover:animate-none motion-reduce:hover:[background-position:50%_center]">SHIMMER</span>
      <span class="text-[10px] tracking-[0.15em] uppercase text-thv04-dim text-center">shimmer keyframe</span>
    </div>
    <div class="flex flex-col items-center gap-5 px-6 py-12 rounded-2xl bg-white/[0.025] border border-white/[0.07]">
      <span tabindex="0" class="inline-block text-[clamp(1.6rem,4vw,2.4rem)] font-black tracking-[0.06em] text-thv04-text bg-clip-text bg-[linear-gradient(135deg,#f43f5e,#f97316)] rounded-xs transition-[color,filter] duration-400 hover:text-transparent hover:[filter:hue-rotate(120deg)_saturate(1.4)] focus-visible:text-transparent focus-visible:[filter:hue-rotate(120deg)_saturate(1.4)] focus-visible:outline-2 focus-visible:outline-offset-6 focus-visible:outline-thv04-ring motion-reduce:transition-none">DUOTONE</span>
      <span class="text-[10px] tracking-[0.15em] uppercase text-thv04-dim text-center">dual-tone color swap</span>
    </div>
    <div class="flex flex-col items-center gap-5 px-6 py-12 rounded-2xl bg-white/[0.025] border border-white/[0.07]">
      <span tabindex="0" class="inline-block text-[clamp(1.6rem,4vw,2.4rem)] font-black tracking-[0.06em] text-thv04-text bg-clip-text bg-[linear-gradient(135deg,#06b6d4_0%,#a21caf_50%,#06b6d4_100%)] [background-size:200%_200%] [background-position:bottom_right] rounded-xs transition-[background-position,color] duration-600 ease-[cubic-bezier(.4,0,.2,1)] hover:text-transparent hover:[background-position:top_left] focus-visible:text-transparent focus-visible:[background-position:top_left] focus-visible:outline-2 focus-visible:outline-offset-6 focus-visible:outline-thv04-ring motion-reduce:transition-none">PRISM</span>
      <span class="text-[10px] tracking-[0.15em] uppercase text-thv04-dim text-center">diagonal sweep</span>
    </div>
  </div>
</section>
@import "tailwindcss";

@theme {
  --color-thv04-bg: #06040f;
  --color-thv04-bg: oklch(0.11 0.02 285);
  --color-thv04-text: #d4d4f7;
  --color-thv04-text: oklch(0.87 0.05 290);
  --color-thv04-dim: #555555;
  --color-thv04-dim: oklch(0.46 0 0);
  --color-thv04-ring: #8b5cf6;
  --color-thv04-ring: oklch(0.63 0.21 295);
  --font-thv04-sans: 'Space Grotesk', system-ui, sans-serif;
  --animate-thv04-shimmer: thv04-shimmer .8s linear infinite;
}

.thv-04 {
  width: 100%;
  min-height: 100svh;
}

.thv-04 ::selection {
  background: var(--color-thv04-ring);
  color: #fff;
}

@keyframes thv04-shimmer {
  0% {
    background-position: -100% center;
  }

  100% {
    background-position: 200% center;
  }
}

Setup — do this once per project

Skip this if your project already runs Tailwind v4.

1Load Tailwind
<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.

2Add the stylesheetRequiredthe @theme block is what makes the custom utilities exist
@import "tailwindcss";

@theme {
  --color-thv04-bg: #06040f;
  --color-thv04-bg: oklch(0.11 0.02 285);
  --color-thv04-text: #d4d4f7;
  --color-thv04-text: oklch(0.87 0.05 290);
  --color-thv04-dim: #555555;
  --color-thv04-dim: oklch(0.46 0 0);
  --color-thv04-ring: #8b5cf6;
  --color-thv04-ring: oklch(0.63 0.21 295);
  --font-thv04-sans: 'Space Grotesk', system-ui, sans-serif;
  --animate-thv04-shimmer: thv04-shimmer .8s linear infinite;
}

.thv-04 {
  width: 100%;
  min-height: 100svh;
}

.thv-04 ::selection {
  background: var(--color-thv04-ring);
  color: #fff;
}

@keyframes thv04-shimmer {
  0% {
    background-position: -100% center;
  }

  100% {
    background-position: 200% center;
  }
}
3Fonts used by this demooptional — skip if you have your own type stack
<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&family=JetBrains+Mono:wght@400;500;600;800&display=swap">

What changed in the port

Which parts became utilities, which stayed CSS, and why.

  • This is the port with the best ratio: -webkit-background-clip:text; background-clip:text; color:transparent becomes bg-clip-text hover:text-transparent, prefixes handled by the compiler.
  • UI change from the CSS original: every word keeps a solid resting colour and only goes transparent on hover/focus, so a failed clip can never leave an invisible heading — and each has a focus-visible: twin.
  • motion-reduce:hover:animate-none on the shimmer pins the gradient at a fixed position rather than removing the reveal: the user still gets the colour, just not the loop.
Paste this into ChatGPT, Claude, Cursor, or any coding assistant. The block below is pre-framed with everything the AI needs to integrate this demo into your project — markup, styles, scoping notes, and the source URL. Hit Copy and paste straight into your chat.
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 Reveal Hover Effect
Source: https://codefronts.com/motion/tailwind-css-hover-effects/tailwind-gradient-text-reveal-hover-effect/

Six ways to paint a gradient onto letterforms on hover — position wipe, radial burst, rainbow shift, shimmer keyframe, duotone hue swap and a diagonal sweep. bg-clip-text and text-transparent are first-class utilities, which makes this the port that shrinks the most.
## HTML
```html
<section class="thv-04 w-full min-h-svh grid place-items-center bg-thv04-bg font-thv04-sans px-6 py-14">
  <div class="w-[min(900px,100%)] grid grid-cols-[repeat(auto-fit,minmax(230px,1fr))] gap-8">
    <div class="flex flex-col items-center gap-5 px-6 py-12 rounded-2xl bg-white/[0.025] border border-white/[0.07]">
      <span tabindex="0" class="inline-block text-[clamp(1.6rem,4vw,2.4rem)] font-black tracking-[0.06em] text-thv04-text bg-clip-text bg-[linear-gradient(90deg,#7c3aed,#06b6d4,#10b981)] [background-size:200%_auto] [background-position:right_center] rounded-xs transition-[background-position,color] duration-500 ease-[cubic-bezier(.4,0,.2,1)] hover:text-transparent hover:[background-position:left_center] focus-visible:text-transparent focus-visible:[background-position:left_center] focus-visible:outline-2 focus-visible:outline-offset-6 focus-visible:outline-thv04-ring motion-reduce:transition-none">AURORA</span>
      <span class="text-[10px] tracking-[0.15em] uppercase text-thv04-dim text-center">gradient position wipe</span>
    </div>
    <div class="flex flex-col items-center gap-5 px-6 py-12 rounded-2xl bg-white/[0.025] border border-white/[0.07]">
      <span tabindex="0" class="inline-block text-[clamp(1.6rem,4vw,2.4rem)] font-black tracking-[0.06em] text-thv04-text bg-clip-text bg-[radial-gradient(circle_at_50%_50%,#f59e0b,#ef4444,#7c3aed)] [background-size:0%_0%] [background-position:center] bg-no-repeat rounded-xs transition-[background-size,color] duration-500 ease-[cubic-bezier(.4,0,.2,1)] hover:text-transparent hover:[background-size:200%_200%] focus-visible:text-transparent focus-visible:[background-size:200%_200%] focus-visible:outline-2 focus-visible:outline-offset-6 focus-visible:outline-thv04-ring motion-reduce:transition-none">RADIAL</span>
      <span class="text-[10px] tracking-[0.15em] uppercase text-thv04-dim text-center">radial-gradient burst</span>
    </div>
    <div class="flex flex-col items-center gap-5 px-6 py-12 rounded-2xl bg-white/[0.025] border border-white/[0.07]">
      <span tabindex="0" class="inline-block text-[clamp(1.6rem,4vw,2.4rem)] font-black tracking-[0.06em] text-thv04-text bg-clip-text bg-[linear-gradient(90deg,#f43f5e,#f59e0b,#10b981,#06b6d4,#6d28d9,#f43f5e)] [background-size:400%_auto] [background-position:0%_center] rounded-xs transition-[background-position,color] duration-600 hover:text-transparent hover:[background-position:100%_center] focus-visible:text-transparent focus-visible:[background-position:100%_center] focus-visible:outline-2 focus-visible:outline-offset-6 focus-visible:outline-thv04-ring motion-reduce:transition-none">SPECTRUM</span>
      <span class="text-[10px] tracking-[0.15em] uppercase text-thv04-dim text-center">rainbow hue-shift</span>
    </div>
    <div class="flex flex-col items-center gap-5 px-6 py-12 rounded-2xl bg-white/[0.025] border border-white/[0.07]">
      <span tabindex="0" class="inline-block text-[clamp(1.6rem,4vw,2.4rem)] font-black tracking-[0.06em] text-thv04-text bg-clip-text bg-[linear-gradient(105deg,#c4b5fd_0%,#fff_40%,#7c3aed_55%,#c4b5fd_100%)] [background-size:200%_auto] rounded-xs transition-colors duration-300 hover:text-transparent hover:animate-thv04-shimmer focus-visible:text-transparent focus-visible:animate-thv04-shimmer focus-visible:outline-2 focus-visible:outline-offset-6 focus-visible:outline-thv04-ring motion-reduce:hover:animate-none motion-reduce:hover:[background-position:50%_center]">SHIMMER</span>
      <span class="text-[10px] tracking-[0.15em] uppercase text-thv04-dim text-center">shimmer keyframe</span>
    </div>
    <div class="flex flex-col items-center gap-5 px-6 py-12 rounded-2xl bg-white/[0.025] border border-white/[0.07]">
      <span tabindex="0" class="inline-block text-[clamp(1.6rem,4vw,2.4rem)] font-black tracking-[0.06em] text-thv04-text bg-clip-text bg-[linear-gradient(135deg,#f43f5e,#f97316)] rounded-xs transition-[color,filter] duration-400 hover:text-transparent hover:[filter:hue-rotate(120deg)_saturate(1.4)] focus-visible:text-transparent focus-visible:[filter:hue-rotate(120deg)_saturate(1.4)] focus-visible:outline-2 focus-visible:outline-offset-6 focus-visible:outline-thv04-ring motion-reduce:transition-none">DUOTONE</span>
      <span class="text-[10px] tracking-[0.15em] uppercase text-thv04-dim text-center">dual-tone color swap</span>
    </div>
    <div class="flex flex-col items-center gap-5 px-6 py-12 rounded-2xl bg-white/[0.025] border border-white/[0.07]">
      <span tabindex="0" class="inline-block text-[clamp(1.6rem,4vw,2.4rem)] font-black tracking-[0.06em] text-thv04-text bg-clip-text bg-[linear-gradient(135deg,#06b6d4_0%,#a21caf_50%,#06b6d4_100%)] [background-size:200%_200%] [background-position:bottom_right] rounded-xs transition-[background-position,color] duration-600 ease-[cubic-bezier(.4,0,.2,1)] hover:text-transparent hover:[background-position:top_left] focus-visible:text-transparent focus-visible:[background-position:top_left] focus-visible:outline-2 focus-visible:outline-offset-6 focus-visible:outline-thv04-ring motion-reduce:transition-none">PRISM</span>
      <span class="text-[10px] tracking-[0.15em] uppercase text-thv04-dim text-center">diagonal sweep</span>
    </div>
  </div>
</section>
```
## CSS
```css
@import "tailwindcss";

@theme {
  --color-thv04-bg: #06040f;
  --color-thv04-bg: oklch(0.11 0.02 285);
  --color-thv04-text: #d4d4f7;
  --color-thv04-text: oklch(0.87 0.05 290);
  --color-thv04-dim: #555555;
  --color-thv04-dim: oklch(0.46 0 0);
  --color-thv04-ring: #8b5cf6;
  --color-thv04-ring: oklch(0.63 0.21 295);
  --font-thv04-sans: 'Space Grotesk', system-ui, sans-serif;
  --animate-thv04-shimmer: thv04-shimmer .8s linear infinite;
}

.thv-04 {
  width: 100%;
  min-height: 100svh;
}

.thv-04 ::selection {
  background: var(--color-thv04-ring);
  color: #fff;
}

@keyframes thv04-shimmer {
  0% {
    background-position: -100% center;
  }

  100% {
    background-position: 200% center;
  }
}
```

How this works

Clipping is a utility; the gradient stays arbitrary. bg-clip-text emits both the prefixed and unprefixed declarations, and text-transparent is the mandatory partner. The gradient itself is bg-[linear-gradient(90deg,#7c3aed,#06b6d4,#10b981)] — Tailwind's bg-linear-* utilities exist, but a three-stop brand ramp reads better stated once.

Gradients do not tween; positions do. Every variant animates background-position or background-size across an oversized gradient, exactly as the CSS original did, because interpolating between two gradient values is not a thing browsers do.

Colour on the way out. Each word is a readable solid colour at rest and only becomes text-transparent under hover or focus, so the text is never invisible in a browser that fails to paint the clip.

Make it yours

  • Reverse the wipe by swapping the two [background-position:...] values.
  • A slower melt: duration-1000 with [background-size:300%_auto].
  • Shimmer pace lives in one @theme line: --animate-thv04-shimmer: thv04-shimmer .6s linear infinite.

Gotchas — read before shipping

  • bg-clip-text without text-transparent shows nothing — the gradient is behind opaque glyphs. Both utilities always travel together.
  • Keep the resting colour solid: if the element is text-transparent at rest and the clip fails, the word vanishes entirely.
  • filter on the duotone variant applies to the whole element, so don't nest icons inside the word.

Browser support

ChromeSafariFirefoxEdge
111+16.4+128+111+

background-clip: text is Baseline with the -webkit- prefix Tailwind emits for you.

Techniques used in this demo

Utilitiesfirst-class utility or variant

Plain CSSno Tailwind surface

Search CodeFronts

Loading…