About this generator
Most gradient text tools give you two colour pickers over a grey box. That is enough to produce a CSS declaration and not enough to ship a headline — because the three things that actually decide whether gradient text works are the type it sits on, what happens when the line wraps, and whether it stays readable at every point along the ramp. This tool is built around those three.
Real type controls. Font stack, size, weight, letter-spacing, line-height and an optional wrap width, because a ramp reads completely differently at 300 weight than at 800. Thin strokes have too few pixels to carry a colour transition, which is why almost every gradient headline in the wild is bold — and why gradient body copy almost never works.
The multiline preview. On a block element one ramp spans the whole box, so a three-line headline can end back near its starting colour. On an inline element every line gets its own complete ramp. Single-line headlines look identical either way, so this normally surfaces in production after the copy changes. Toggle the wrapped preview and switch between the two modes to decide before it ships.
Contrast at the worst point. WCAG applies to every glyph, so the number that matters is the minimum along the ramp, not the average of the stops. The status bar samples between stops, reports the weakest ratio with the exact colour that caused it, and switches between the 3:1 and 4.5:1 thresholds based on whether your size and weight qualify as large text.
Everything else follows from those: an @supports fallback so an unsupported browser shows a solid headline rather than an invisible one, OKLab and OKLCH interpolation to remove the grey dead zone between complementary colours, stroke and hollow lettering, drop-shadow glow, a light-mode ramp pair, and five exports — CSS, per-letter HTML, Tailwind, React, and SVG for OG images and email. Prefer browsing finished examples instead? See the 20 CSS gradient text designs and 20 CSS text gradient effects collections.
How to use
Gradient text snippets
/* The complete pattern, fallback first. */
.gradient-text {
font-size: 64px;
font-weight: 800;
display: inline-block;
/* Painted if the clip never applies — without this the
headline is invisible, not merely unstyled. */
color: #ff5a5f;
}
@supports (background-clip: text) or (-webkit-background-clip: text) {
.gradient-text {
background-image: linear-gradient(100deg in oklab, #ff8a3d, #a03dff);
-webkit-background-clip: text;
background-clip: text;
-webkit-text-fill-color: transparent;
color: transparent;
}
}/* Block: ONE ramp across the whole element. A three-line
headline can end line 3 back near the starting colour. */
h1.block { display: block; }
/* Inline: every LINE BOX gets its own complete ramp. */
h1.inline { display: inline; }
/* Neither is wrong. Single-line headlines look identical,
so this only shows up once the copy wraps. *//* Registering the custom property lets the angle interpolate
smoothly. Without @property it steps between integers. */
@property --gt-hue {
syntax: '<angle>';
initial-value: 0deg;
inherits: false;
}
.gradient-text {
background-image: linear-gradient(100deg in oklab, #ff8a3d, #a03dff);
background-size: 220% auto;
-webkit-background-clip: text;
background-clip: text;
-webkit-text-fill-color: transparent;
}
@media (prefers-reduced-motion: no-preference) {
.gradient-text { animation: gradient-text-pan 6s linear infinite; }
}
@keyframes gradient-text-pan {
to { background-position: 220% center; }
}/* Outlined gradient text, and hollow (stroke only). */
.outlined {
background-image: linear-gradient(100deg, #ff8a3d, #a03dff);
-webkit-background-clip: text;
background-clip: text;
-webkit-text-fill-color: transparent;
-webkit-text-stroke: 2px #ffffff;
}
/* Hollow: no fill at all, just the outline. The clip is
dropped because a gradient fill would hide the stroke. */
.hollow {
-webkit-text-fill-color: transparent;
-webkit-text-stroke: 2px #a03dff;
}/* drop-shadow follows the glyph alpha. text-shadow would
paint through the transparent fill; box-shadow would draw
a rectangle around the element box. */
.glowing {
background-image: linear-gradient(100deg, #a5f3fc, #c4b5fd);
-webkit-background-clip: text;
background-clip: text;
-webkit-text-fill-color: transparent;
filter: drop-shadow(0 0 18px #a03dff);
}/* A ramp tuned against dark goes muddy on white.
Same geometry, different stops. */
.gradient-text {
background-image: linear-gradient(100deg in oklab, #3dffb4, #a03dff);
}
@media (prefers-color-scheme: light) {
.gradient-text {
background-image: linear-gradient(100deg in oklab, #7c3aed, #db2777);
color: #a8319b; /* fallback for light mode too */
}
}<!-- Renders where background-clip:text cannot: OG images,
email clients, PDF export. -->
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1200 200"
role="img" aria-label="Ship it in one paste">
<defs>
<linearGradient id="gt" x1="0" y1="0" x2="1" y2="0">
<stop offset="0%" stop-color="#ff8a3d" />
<stop offset="100%" stop-color="#a03dff" />
</linearGradient>
</defs>
<text x="600" y="120" text-anchor="middle"
font-size="64" font-weight="800" fill="url(#gt)">
Ship it in one paste
</text>
</svg><!-- bg-clip-text and text-transparent are a required pair.
The arbitrary value keeps exact stops and interpolation,
which bg-gradient-to-* cannot express. -->
<h1 class="bg-[linear-gradient(100deg,#ff8a3d,#a03dff)]
bg-clip-text text-transparent
text-[64px] font-[800] tracking-[-0.02em]">
Ship it in one paste
</h1>
<!-- Tailwind has no utility for the @supports fallback.
Put this in your global stylesheet. -->Browser support
background-clip: text is Baseline and has shipped in every engine for years, though the -webkit- prefix is still required for older WebKit and is emitted automatically. The @supports fallback covers the rest. oklab and oklch interpolation need Chrome 111+, Safari 16.2+ and Firefox 113+ — pick sRGB if you must support older engines, and the ramp still works, it just blends less evenly. @property (used by the hue-spin animation) needs Chrome 85+, Safari 16.4+ and Firefox 128+; where it is missing the animation simply does not run. Every animation ships inside a prefers-reduced-motion guard.
Pro tips
Frequently asked questions
How do you make gradient text in CSS?
Three declarations working together. Put a gradient on background-image, clip that background to the shape of the glyphs with background-clip: text, then make the text itself transparent so the background shows through — -webkit-text-fill-color: transparent, with color: transparent as the standard equivalent. The -webkit- prefix is still required for older WebKit and costs nothing to include, so ship both. The element also needs a layout box the gradient can fill, which in practice means display: inline-block or block — a plain inline element sized to its text works, but behaves differently once the text wraps. This generator emits all of it, in the right order, with the fallback attached.
Why is my gradient text invisible?
Because the recipe makes the text transparent and relies on the background to paint it — so if background-clip: text does not apply, nothing renders the glyphs at all and the headline vanishes completely. This is the single most common failure and it is not a graceful degradation; it is a blank hero section. The causes are usually one of: the -webkit- prefixed property missing on an older WebKit build, background-clip being overridden by a later rule or a utility class, the element having no background image set (a solid background-color does not work — it must be a background-image, which includes gradients), or the text sitting in an element with no layout box. The fix is to always paint a solid color first and wrap the clip in @supports (background-clip: text) or (-webkit-background-clip: text). The generator does this by default; leave the fallback toggle on.
Why does my gradient restart on the second line of a heading?
Because of how the gradient box relates to line boxes, and it differs between block and inline. On a block element the background covers the whole element box, so the ramp is distributed vertically across every line at once — a three-line headline puts line one at the start of the ramp and line three at the end, which frequently lands back near the starting colour on a looping palette. On an inline element each line box gets its own complete gradient, so all three lines run the full ramp independently. Neither behaviour is a bug and neither is universally correct; you have to pick. The catch is that a single-line headline looks identical either way, so this only surfaces in production after the copy changes and the line wraps. Toggle the wrapped-headline preview in this generator and switch between Block and Inline to see both.
Is gradient text accessible?
It can be, but it needs more care than solid text because the contrast ratio changes continuously along the ramp. WCAG 1.4.3 requires 4.5:1 for body text and 3:1 for large text — 24px and above, or 18.66px and above at 700 weight or heavier. The mistake is checking the average or the endpoints: a ramp running from pale yellow to mid orange on white passes at one end and fails in the middle, and every glyph has to pass. This generator samples across the entire ramp and reports the worst ratio it finds, along with the exact colour where it occurs, so you can move one stop rather than rebuild the palette. Two other points: if you apply the gradient per letter or per word, the markup becomes one span per unit and screen readers may announce the text character by character, so the wrapper needs aria-label carrying the full string — the HTML export includes it. And any animated ramp belongs inside a prefers-reduced-motion: no-preference guard, which the generator adds automatically.
What is the difference between sRGB, OKLab and OKLCH interpolation?
It is how the browser calculates the colours between your stops, and it visibly changes the result. sRGB is the historic default and interpolates in a space that is not perceptually uniform, so blends between complementary colours dip through a desaturated grey zone in the middle — blue to orange and purple to yellow are the classic examples, and the muddy midpoint is why some gradients look dull no matter which endpoints you pick. OKLab is perceptually uniform, so brightness stays steady across the blend and the grey dead zone disappears. OKLCH is the polar form of the same space and interpolates hue around the colour wheel, which produces the vivid sweep you want for rainbow and holographic ramps rather than a direct line between two points. Syntax is linear-gradient(100deg in oklab, ...). It needs Chrome 111+, Safari 16.2+ or Firefox 113+; older engines ignore the space and fall back to sRGB, so the gradient still renders.
How do you add an outline or glow to gradient text?
For the outline, -webkit-text-stroke draws a border on the glyph edges and composes correctly with the gradient fill. For hollow lettering — outline only, no fill — keep the text transparent and drop the background clip entirely, because a gradient fill would sit on top of and obscure the stroke. For the glow, the property to use is filter: drop-shadow(), not text-shadow: because the text fill is transparent, a text shadow renders through the glyphs and reads as a smear rather than a light source. drop-shadow operates on the composited alpha of the element, so it traces the visible gradient shape precisely. box-shadow is wrong for a different reason — it draws a rectangle around the element box with no relationship to the letterforms at all.
Does gradient text work in Tailwind CSS?
Yes — bg-clip-text paired with text-transparent is the required combination, and both must be present. For the gradient itself, the built-in bg-gradient-to-r style utilities work for simple two or three stop ramps using theme colours, but they cannot express an explicit angle in degrees or an interpolation space, so anything precise needs an arbitrary value: bg-[linear-gradient(100deg_in_oklab,#ff8a3d,#a03dff)]. Note that Tailwind has no utility that can express the @supports fallback, so the solid fallback colour has to live in your global stylesheet — this generator's Tailwind export prints the class list and includes that stylesheet snippet as a comment so it does not get forgotten.
How do I get gradient text into an Open Graph image or an email?
Use SVG instead, because neither social preview renderers nor most email clients support background-clip: text. The SVG approach defines a real <linearGradient> in <defs> and applies it with fill="url(#id)" on a <text> element, which is a completely different mechanism with far broader support and which rasterises correctly when an OG image pipeline screenshots the markup. This generator's SVG export produces exactly that, sized for a standard 1200-wide OG canvas and carrying role="img" plus aria-label so it remains accessible. The one caveat is fonts: an SVG rendered on a server only has access to fonts installed there, so for OG pipelines either stick to a system font stack or convert the text to paths.
Related tools
Premium design system · Untitled UI
AffiliateTuning one value? Get the whole system.
- 900+ colour, type & effect styles (Pro)
- 10,000+ components & variants (Pro)
Affiliate link: we may earn a commission at no extra cost to you.
Untitled UI Pro: 900+ colour, type and effect styles for Figma · from $129 one-timeGet Untitled UI Pro →Affiliate link