Gradient text in Tailwind CSS, static and animated
Make gradient text with Tailwind's bg-clip-text, animate it with one keyframe, or fill it with a live shader.
Updated
To make gradient text in Tailwind CSS, paint a gradient background on the text and clip it to the glyphs with bg-clip-text text-transparent:
<h1
class="w-fit bg-linear-to-r from-pink-500 via-violet-500 to-sky-400 bg-clip-text pb-1 text-5xl font-semibold text-transparent"
>
Gradient text
</h1>That is Tailwind v4. In Tailwind v3 the gradient class is bg-gradient-to-r, and everything else is the same. The text stays real text: selectable, searchable and read by screen readers.
This post covers three levels: the static gradient above, an animated version in pure CSS, and the free Gradient Text component, which fills the letters with a live shader gradient:
Build something alive
import { GradientText } from "@/components/gradient-text";
export function GradientTextDemo() {
return (
<h2 className="text-5xl font-semibold tracking-tight">
Build something <GradientText>alive</GradientText>
</h2>
);
}
How bg-clip-text works
Three classes do the work:
bg-linear-to-r from-… via-… to-…paints a linear gradient as the element's background. Use any direction (bg-linear-to-br,bg-linear-45) and any colours, including arbitrary ones likefrom-[#ff6b6b].bg-clip-textsetsbackground-clip: text, so the background only shows inside the letter shapes.text-transparenthides the text's own colour so the background shows through.
Three things trip people up:
- A heading spreads the gradient across the page. An
<h1>is a block, so its background is as wide as its container, and short text only shows the first colour or two.w-fitshrinks the box to the text, so the whole gradient lands on the words. - Inline elements wrap the gradient per line. On a
<span>that breaks across lines, each line gets its own slice. Addbox-decoration-cloneto repeat the full gradient on every line, or make the spaninline-blockto keep one gradient across the box. - Descenders get cut off. Tight
leading-nonecan clip the bottom of a "g" or "y", because the background stops at the element's box. Thepb-1in the examples gives them room. Loosening the line height works too.
Animated gradient text in Tailwind
To animate the colours, make the background twice as wide as the text and slide it. Add a keyframe and an animation to your Tailwind v4 CSS:
@theme {
--animate-gradient-x: gradient-x 6s linear infinite;
@keyframes gradient-x {
from {
background-position: 0% center;
}
to {
background-position: 200% center;
}
}
}Then use it with a gradient that starts and ends on the same colour:
<h1
class="w-fit bg-linear-to-r from-pink-500 via-sky-400 to-pink-500 bg-[length:200%_auto] bg-clip-text pb-1 text-5xl font-semibold text-transparent motion-safe:animate-gradient-x"
>
Animated gradient text
</h1>Why it loops without a jump: the background is 200% of the text's width, and moving background-position from 0% to 200% shifts it by exactly one background width. The background repeats, and because the gradient begins and ends on pink, the end frame matches the start. motion-safe: turns the animation off for visitors who prefer reduced motion.
In Tailwind v3, put the keyframe and animation in tailwind.config.js under theme.extend.keyframes and theme.extend.animation instead of @theme.
Live gradient text in React
The CSS version slides one flat gradient sideways. The Gradient Text component fills the letters with a shader gradient instead: soft colour fields that drift through each other, drawn on the GPU and looping seamlessly. Install it with the shadcn CLI:
pnpm dlx shadcn@latest add https://gradients.sh/r/gradient-text.jsonThe CLI adds components/gradient-text.tsx, the shared components/gradient-surface.tsx and the engine in lib/gradient-engine/. Wrap the words you want filled:
import { GradientText } from "@/components/gradient-text";
export function Headline() {
return (
<h1 className="text-5xl font-semibold tracking-tight">
Build something{" "}
<GradientText colors={["#ff6b6b", "#c084fc", "#38bdf8"]}>
alive
</GradientText>
</h1>
);
}Gradient Text takes its font, size and weight from its parent, so style the heading as usual. It renders a <span>, which means it works inside headings, links and buttons.
How it stays accessible
The visible letters are an aria-hidden copy of the text, masked to the glyph shapes with mask-clip: text, with the gradient canvas inside. The real text sits on top with a transparent fill. Selection, copy, find-in-page and screen readers all use that ordinary text. Browsers without text masks, and the server render, get a static version of the same gradient through background-clip: text, so the text is never invisible.
Props
Gradient Text accepts the same gradient props as the background components. Its defaults are tuned for small shapes: crisper (blur 0.2), faster (speed 0.9), no grain, and no pointer or scroll response.
colors: two to six CSS colours, including theme variables likevar(--primary).kind: which gradient fills the text. The default is"mesh";"grain","aurora","waves","radial-glow"and"linear-flow"also work.speedandloopSeconds: how far the colour travels and how often the loop repeats.speed={0}holds it still.scale: higher means smaller, busier colour fields.
The Gradient Text props table lists everything.
Which one to use
| Approach | Moves | JavaScript | Best for |
|---|---|---|---|
bg-clip-text gradient | No | None | Section headings, many gradient words per page |
bg-clip-text + keyframe | Slides sideways | None | A hero word that should shimmer |
| Gradient Text component | Colour fields drift | About 50 KB gzipped with the engine, shared with other gradients.sh components | One or two hero words that should feel alive |
Each Gradient Text draws its own live gradient, so keep it to a headline word or two rather than whole paragraphs. Off screen it stops drawing, and visitors who prefer reduced motion see one still frame.
Whichever you pick, check contrast. Gradient text is only as readable as its lightest colour against the page, so test both ends of the gradient against your background in light and dark mode.
Related
- Stripe-style animated mesh gradient uses the same mesh as a hero background.
- Animated gradient border animates a conic gradient around a card with a keyframe.
- Animated gradient background for shadcn/ui puts a live gradient behind a whole section.
- Animated gradient backgrounds in Tailwind CSS uses the same sliding keyframe on a whole section.
- Metallic gradients in CSS clips a chrome gradient to text the same way, with recipes for gold, copper and rose gold.