Worst point4.19:1

CSS Gradient Text Generator

Your text

Set Lines: Wrapped above the preview, then switch One ramp and Per line under Box. By default a wrapped headline gets one gradient stretched across every line, so no single line shows the whole palette. Most generators only ever preview one line, so this surfaces in production after the copy changes.

Type
Size
px
Weight
Letter spacing
/100em
Line height
Max width (0 = none)
ch
Box

One ramp stretches a single gradient across all the lines — line one starts it, the last line ends it. Per line gives every line the complete ramp, which needs display: inline together with box-decoration-break: clone. Inline on its own does not do it, which is the part most write-ups get wrong.

Gradient
Angle
deg
#ff8a3d
#ff3d77
#a03dff
Interpolation

sRGB dips through a grey dead zone between complementary colours — blue to orange is the classic case. OKLab and OKLCH hold brightness steady across the blend. OKLCH takes the long way round the hue wheel, which is what you want for rainbow ramps.

Apply ramp across

Per-word and per-letter wrap each unit in its own span so the ramp runs across the line rather than restarting inside every glyph. The HTML export adds aria-label — without it a screen reader announces the headline one letter at a time.

Outline
Stroke width
px
Glow
Blur
px

Uses filter: drop-shadow(), which follows the glyph shape. text-shadow paints under the transparent fill and box-shadow would draw a rectangle behind the text.

Animation

Both modes ship wrapped in prefers-reduced-motion. Hue spin registers --gt-hue via @property so the angle interpolates smoothly instead of stepping.

Light mode pair
Emit a second ramp for light mode

Neon ramps tuned against a dark background go muddy on white. This emits a prefers-color-scheme: light block with a second ramp at the same geometry.

Fallback
Emit @supports fallback

Keep this on. Where background-clip: text does not apply, the text is transparent with nothing painting it and the headline disappears completely. The fallback paints a solid mid-ramp colour first.

Preview on
Lines
live
Preset
Sunset
Gradient
linear 100°
Stops
3
Space
oklab

Ship it in one paste

Weakest#a03dffLarge text · needs 3:1@supports fallback on
23 lines · 752 B
/* The solid colour paints first. The @supports block only wins
where background-clip:text actually applies — without it, an
unsupported browser renders transparent text on nothing and the
headline disappears. */
.gradient-text {
font-family: 'Geist', 'Inter', system-ui, sans-serif;
font-size: 64px;
font-weight: 800;
letter-spacing: -0.020em;
line-height: 1.1;
display: inline-block;
color: #ff3d77;
}
​
@supports (background-clip: text) or (-webkit-background-clip: text) {
.gradient-text {
background-image: linear-gradient(100deg in oklab, #ff8a3d, #ff3d77, #a03dff);
-webkit-background-clip: text;
background-clip: text;
-webkit-text-fill-color: transparent;
color: transparent;
}
}

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

01
Type your actual headline
Not "Lorem ipsum". A ramp reads completely differently on a two-word wordmark than on a nine-word hero line, because the gradient is distributed across the text box — longer text means each colour gets less room. Paste the string you are shipping.
02
Set the type before the colour
Family, size, weight, letter-spacing, line-height. Weight matters more than anything else here: a gradient on 300-weight text shows almost no colour because there are barely any pixels to fill, which is why nearly every gradient headline in the wild is 700 or heavier.
03
Pick a preset, then tune the stops
Twelve starting points — Sunset, Aurora, Ocean, Candy, Gold Foil, Chrome, Holographic, Ember, Mint, Grape, Acid, Mono. Add up to six stops, drag the angle, or switch to radial or conic. Conic is what produces the metallic and holographic looks; a linear ramp cannot.
04
Choose the interpolation space
sRGB is the default everywhere and it dips through a grey dead zone between complementary colours — blue to orange is the classic failure. OKLab holds perceived brightness steady across the blend. OKLCH takes the long way round the hue wheel, which is what you want for rainbow ramps.
05
Decide block vs inline, then preview wrapped
This is the trap nothing else shows you. On a block element one ramp spans the whole box, so a three-line headline restarts its colour on line three. On an inline element every line box gets its own complete ramp. Toggle "Preview as a wrapped headline" and switch between the two — the difference is obvious and it decides which one your design actually needs.
06
Add stroke or glow if the design calls for it
Stroke gives outlined text; turn on Hollow for stroke-only lettering with no fill at all. Glow uses filter: drop-shadow(), which follows the glyph shape — text-shadow paints underneath the transparent fill and box-shadow draws a rectangle behind the whole element.
07
Check the contrast readout
The status bar reports the WORST point anywhere on the ramp against your chosen background, not the average, because WCAG applies to every glyph. It also switches the threshold between 3:1 and 4.5:1 depending on whether your size and weight qualify as large text. Change the background swatch to test the ramp against dark, light, paper and brand grounds.
08
Export to your stack
Five formats: CSS (with the @supports fallback), HTML (the per-word or per-letter span markup plus aria-label), Tailwind arbitrary values, React with TypeScript, and SVG for anywhere the clip does not work at all — OG images, email, PDF.
</>

Gradient text snippets

Complete pattern with fallback
/* 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 vs inline multiline
/* 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. */
Animated ramp
/* 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; }
}
Stroke outline and hollow
/* 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;
}
Glow via drop-shadow
/* 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);
}
Dark and light mode pair
/* 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 */
  }
}
SVG for OG images and email
<!-- 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>
Tailwind
<!-- 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.

Chromev3+
Safariv4+
Firefoxv49+
Edgev79+
✦

Pro tips

01
Always ship the fallback — this is the one that bites
The recipe sets <code>color: transparent</code> and paints the text through the background. If <code>background-clip: text</code> does not apply for any reason, there is nothing painting the glyphs and <strong>the headline disappears completely</strong> — not degraded, invisible. The generator emits a solid mid-ramp colour first and wraps the clip in <code>@supports</code>, so the worst case is a flat-coloured headline instead of a blank hero. Leave the toggle on unless you have a specific reason not to.
02
Block vs inline changes where the ramp restarts
Verified in a browser, not theory: on a <strong>block</strong> element the gradient covers the element box, so on a three-line headline the third line sits at the far end of the ramp and can land back on the starting colour. On an <strong>inline</strong> element every line box gets its own full gradient, so all three lines run the complete ramp independently. Single-line headlines look identical either way, which is why this only surfaces after the copy changes and the line wraps in production.
03
Weight is the real variable
A gradient needs pixels to show itself. At 300 weight the strokes are too thin to carry a colour transition and the effect reads as a muddy single hue; at 800 the same ramp is unmistakable. If a gradient headline looks weak, raise the weight before touching the colours. The same logic explains why gradient body copy almost never works — and why the contrast threshold in the status bar tightens from 3:1 to 4.5:1 once your text drops below the large-text cutoff.
04
Contrast is decided by the worst stop, not the average
A ramp from pale yellow to mid orange on white passes comfortably at one end and fails at the other. Averaging the stops reports a pass on text that is genuinely unreadable in the middle. This tool samples between the stops and reports the minimum along with the exact colour where it occurs, so you can move that one stop instead of rebuilding the palette. WCAG 1.4.3 needs 4.5:1 for body text and 3:1 for large text (24px+, or 18.66px+ at 700 weight).
05
Use drop-shadow for glow, never text-shadow
<code>text-shadow</code> renders behind the text fill — and the fill is transparent, so the shadow shows through the glyphs and the result looks smeared rather than lit. <code>filter: drop-shadow()</code> operates on the composited alpha of the element, so it follows the visible gradient shape exactly. <code>box-shadow</code> is worse again: it draws a rectangle around the element box with no relationship to the letterforms.
06
Per-letter ramps need aria-label
Applying the gradient per word or per letter means wrapping every unit in its own span. Screen readers can treat a run of single-character spans as separate items and announce the headline one letter at a time. The HTML export puts <code>aria-label</code> carrying the full string on the wrapper for exactly this reason. The same applies to any decorative letter-splitting technique, including the ones driven by JavaScript.
07
A dark-tuned ramp usually fails on white
Neon and pastel ramps are chosen against dark backgrounds where they glow. Put the identical stops on white and they turn pale and muddy, often dropping below 3:1. Turning on the light-mode pair emits a <code>prefers-color-scheme: light</code> block with a second ramp at the same angle and type, which is the pattern real design systems ship — the geometry stays, the colours change.
08
SVG is the escape hatch for OG images and email
Neither social preview images nor most email clients render <code>background-clip: text</code>. The SVG export uses a real <code>&lt;linearGradient&gt;</code> with <code>fill="url(#id)"</code> on a <code>&lt;text&gt;</code> element, which renders as actual gradient text anywhere SVG is supported, and rasterises correctly when an OG image pipeline screenshots it. It carries <code>role="img"</code> plus <code>aria-label</code> so it stays accessible.
?

Frequently asked questions

01

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.

02

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.

03

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.

04

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.

05

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.

06

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.

07

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.

08

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

Search CodeFronts

Loading…