20 CSS Text Gradient Effects 15 / 20
Multi Color Rainbow Text Gradient CSS
A six-stop HSL hue-wheel gradient cycling 0°→320°, with a continuously animated version driven by background-position shifting.
The code
<div class="tg-15">
<div class="tg-15__scene">
<h1 class="tg-15__rainbow">Spectacular</h1>
<h2 class="tg-15__rainbow tg-15__anim">Iridescent</h2>
<div class="tg-15__tag-cloud">
<span class="tg-15__tag tg-15__t1">Design</span>
<span class="tg-15__tag tg-15__t2">Colour</span>
<span class="tg-15__tag tg-15__t3">Motion</span>
<span class="tg-15__tag tg-15__t4">Type</span>
<span class="tg-15__tag tg-15__t5">Play</span>
</div>
<p class="tg-15__note">4+ colour stops in a <code>linear-gradient</code> create a true rainbow spectrum. Keep saturation high and transition through the full hue wheel (0°→360°) for the most vivid result.</p>
</div>
</div> <div class="tg-15">
<div class="tg-15__scene">
<h1 class="tg-15__rainbow">Spectacular</h1>
<h2 class="tg-15__rainbow tg-15__anim">Iridescent</h2>
<div class="tg-15__tag-cloud">
<span class="tg-15__tag tg-15__t1">Design</span>
<span class="tg-15__tag tg-15__t2">Colour</span>
<span class="tg-15__tag tg-15__t3">Motion</span>
<span class="tg-15__tag tg-15__t4">Type</span>
<span class="tg-15__tag tg-15__t5">Play</span>
</div>
<p class="tg-15__note">4+ colour stops in a <code>linear-gradient</code> create a true rainbow spectrum. Keep saturation high and transition through the full hue wheel (0°→360°) for the most vivid result.</p>
</div>
</div>.tg-15, .tg-15 *, .tg-15 *::before, .tg-15 *::after { margin:0; padding:0; box-sizing:border-box; }
.tg-15 ::selection { background:#ec4899; color:#fff; }
.tg-15 {
--bg: #06030c;
--text: #e2e8f0;
--muted: #64748b;
font-family: system-ui, -apple-system, sans-serif;
background: var(--bg);
min-height: 100vh;
display: flex;
align-items: center;
justify-content: center;
padding: 40px 24px;
}
.tg-15__scene { max-width: 640px; width: 100%; text-align: center; }
/* Full-spectrum rainbow: 6 stops cycling through hsl hues */
.tg-15__rainbow {
background: linear-gradient(
90deg,
hsl(0, 100%, 60%) 0%,
hsl(45, 100%, 60%) 20%,
hsl(120, 100%, 45%) 40%,
hsl(200, 100%, 55%) 60%,
hsl(270, 100%, 65%) 80%,
hsl(320, 100%, 60%) 100%
);
background-size: 200% 100%;
-webkit-background-clip: text;
background-clip: text;
-webkit-text-fill-color: transparent;
color: transparent;
font-weight: 900;
letter-spacing: -.04em;
line-height: 1;
display: block;
}
.tg-15__rainbow:first-child { font-size: clamp(3rem, 10vw, 5.5rem); margin-bottom: 6px; }
.tg-15__rainbow.tg-15__anim {
font-size: clamp(1.8rem, 6vw, 3.5rem);
background: linear-gradient(
90deg,
hsl(200, 100%, 60%) 0%,
hsl(270, 100%, 65%) 16%,
hsl(320, 100%, 60%) 33%,
hsl(0, 100%, 60%) 50%,
hsl(45, 100%, 60%) 66%,
hsl(120, 100%, 45%) 83%,
hsl(200, 100%, 60%) 100%
);
background-size: 200% 100%;
-webkit-background-clip: text;
background-clip: text;
-webkit-text-fill-color: transparent;
animation: tg-15-shift 3s linear infinite;
margin-bottom: 32px;
}
@keyframes tg-15-shift {
0% { background-position: 0% 0%; }
100% { background-position: 200% 0%; }
}
.tg-15__tag-cloud { display: flex; gap: 10px; justify-content: center; flex-wrap: wrap; margin-bottom: 28px; }
.tg-15__tag {
font-size: .85rem;
font-weight: 700;
padding: 6px 16px;
border-radius: 99px;
border: 1.5px solid transparent;
-webkit-background-clip: text;
background-clip: text;
-webkit-text-fill-color: transparent;
color: transparent;
position: relative;
}
.tg-15__tag::before {
content: '';
position: absolute;
inset: 0;
border-radius: 99px;
border: 1.5px solid currentColor;
opacity: .3;
}
/* background-image (not shorthand) — shorthand resets background-clip
to border-box and the .tg-15__tag text clipping silently fails. */
.tg-15__t1 { background-image: linear-gradient(90deg,hsl(0,90%,60%),hsl(30,90%,60%)); }
.tg-15__t2 { background-image: linear-gradient(90deg,hsl(60,90%,50%),hsl(120,90%,45%)); }
.tg-15__t3 { background-image: linear-gradient(90deg,hsl(160,90%,45%),hsl(200,90%,55%)); }
.tg-15__t4 { background-image: linear-gradient(90deg,hsl(240,90%,65%),hsl(280,90%,65%)); }
.tg-15__t5 { background-image: linear-gradient(90deg,hsl(300,90%,60%),hsl(340,90%,60%)); }
.tg-15__note {
font-size: .8rem;
color: var(--muted);
line-height: 1.65;
}
.tg-15__note code {
background: rgba(255,255,255,.07);
border-radius: 3px;
padding: 1px 5px;
color: hsl(200,90%,65%);
}
@media (prefers-reduced-motion: reduce) {
.tg-15__anim { animation: none; background-position: 0% 0%; }
} .tg-15, .tg-15 *, .tg-15 *::before, .tg-15 *::after { margin:0; padding:0; box-sizing:border-box; }
.tg-15 ::selection { background:#ec4899; color:#fff; }
.tg-15 {
--bg: #06030c;
--text: #e2e8f0;
--muted: #64748b;
font-family: system-ui, -apple-system, sans-serif;
background: var(--bg);
min-height: 100vh;
display: flex;
align-items: center;
justify-content: center;
padding: 40px 24px;
}
.tg-15__scene { max-width: 640px; width: 100%; text-align: center; }
/* Full-spectrum rainbow: 6 stops cycling through hsl hues */
.tg-15__rainbow {
background: linear-gradient(
90deg,
hsl(0, 100%, 60%) 0%,
hsl(45, 100%, 60%) 20%,
hsl(120, 100%, 45%) 40%,
hsl(200, 100%, 55%) 60%,
hsl(270, 100%, 65%) 80%,
hsl(320, 100%, 60%) 100%
);
background-size: 200% 100%;
-webkit-background-clip: text;
background-clip: text;
-webkit-text-fill-color: transparent;
color: transparent;
font-weight: 900;
letter-spacing: -.04em;
line-height: 1;
display: block;
}
.tg-15__rainbow:first-child { font-size: clamp(3rem, 10vw, 5.5rem); margin-bottom: 6px; }
.tg-15__rainbow.tg-15__anim {
font-size: clamp(1.8rem, 6vw, 3.5rem);
background: linear-gradient(
90deg,
hsl(200, 100%, 60%) 0%,
hsl(270, 100%, 65%) 16%,
hsl(320, 100%, 60%) 33%,
hsl(0, 100%, 60%) 50%,
hsl(45, 100%, 60%) 66%,
hsl(120, 100%, 45%) 83%,
hsl(200, 100%, 60%) 100%
);
background-size: 200% 100%;
-webkit-background-clip: text;
background-clip: text;
-webkit-text-fill-color: transparent;
animation: tg-15-shift 3s linear infinite;
margin-bottom: 32px;
}
@keyframes tg-15-shift {
0% { background-position: 0% 0%; }
100% { background-position: 200% 0%; }
}
.tg-15__tag-cloud { display: flex; gap: 10px; justify-content: center; flex-wrap: wrap; margin-bottom: 28px; }
.tg-15__tag {
font-size: .85rem;
font-weight: 700;
padding: 6px 16px;
border-radius: 99px;
border: 1.5px solid transparent;
-webkit-background-clip: text;
background-clip: text;
-webkit-text-fill-color: transparent;
color: transparent;
position: relative;
}
.tg-15__tag::before {
content: '';
position: absolute;
inset: 0;
border-radius: 99px;
border: 1.5px solid currentColor;
opacity: .3;
}
/* background-image (not shorthand) — shorthand resets background-clip
to border-box and the .tg-15__tag text clipping silently fails. */
.tg-15__t1 { background-image: linear-gradient(90deg,hsl(0,90%,60%),hsl(30,90%,60%)); }
.tg-15__t2 { background-image: linear-gradient(90deg,hsl(60,90%,50%),hsl(120,90%,45%)); }
.tg-15__t3 { background-image: linear-gradient(90deg,hsl(160,90%,45%),hsl(200,90%,55%)); }
.tg-15__t4 { background-image: linear-gradient(90deg,hsl(240,90%,65%),hsl(280,90%,65%)); }
.tg-15__t5 { background-image: linear-gradient(90deg,hsl(300,90%,60%),hsl(340,90%,60%)); }
.tg-15__note {
font-size: .8rem;
color: var(--muted);
line-height: 1.65;
}
.tg-15__note code {
background: rgba(255,255,255,.07);
border-radius: 3px;
padding: 1px 5px;
color: hsl(200,90%,65%);
}
@media (prefers-reduced-motion: reduce) {
.tg-15__anim { animation: none; background-position: 0% 0%; }
}How this works
A six-stop linear-gradient spanning hsl(0,100%,60%) through hsl(320,100%,60%) covers the full visible spectrum in order: red → orange → green → cyan → indigo → magenta. Keeping saturation at 100% and lightness at 45–65% ensures every hue is fully vivid — lower saturation produces a washed-out pastel band rather than a true rainbow.
The animated variant uses background-size: 200% 100% with a looping background-position animation from 0% to 200%. The gradient is cyclic — its last stop matches its first — so the loop is seamless. The static version remains at background-position: 0%, giving users who prefer motion a clean colourful display without the shift.
Customize
- Shift the hue range by changing the starting
hsl(0, …)tohsl(45, …)to begin the spectrum at amber and end at violet, producing a warm-biased rainbow. - Slow the animation from
3sto6sfor a slow colour wash, or increase to1.5sfor a rapid flicker effect — adjustlineartoease-in-outfor a breathing quality. - Reduce to four stops (
0%, 33%, 66%, 100%) for a tighter, more brand-aligned palette — e.g. just orange → purple for a sports or entertainment colour story. - Apply to price numbers or stat callouts by adding the
tg-15__rainbowclass to any element — the full spectrum draws attention to key figures in a dashboard. - Pause the animation on hover with
animation-play-state: pausedto let users freeze the gradient at any colour — useful for gamified or playful UIs.
Watch out for
- A six-stop full-spectrum gradient may produce a visible 'muddiness' around the hue transitions from yellow to green or from green to cyan if saturation dips during interpolation. Fix by adding an additional stop between these pairs holding saturation at 100%.
- On iOS Safari, the rainbow animated variant can occasionally stutter on the first loop iteration before the GPU has cached the composite layer. This self-resolves but can be pre-empted by triggering a dummy animation on page load.
- The two-stop HSL rainbow approach (going from
hsl(0)tohsl(360)) will produce an identical result at both ends because 0° and 360° are the same red hue — the gradient will not loop seamlessly unless intermediate stops are used, as demonstrated in this demo.
Browser support
| Chrome | Safari | Firefox | Edge |
|---|---|---|---|
| 69+ | 12.1+ | 83+ | 69+ |
conic-gradient (used in some shimmer variants) requires Chrome 69+, Safari 12.1+, Firefox 83+ — the rainbow linear-gradient itself has broader support back to 2013.