Gradient Letter Flow
Each letter takes its turn at the CSS keyframe color peak — a luminous wave travels through the word from left to right, continuously.
You'll get access to the interactive demo with a free account.
This effect is part of Effect.Labs — 811 vanilla effects, some free, some premium. Text has 56 effects, including 4 free. Explore the category →
3 usage examples



How it works
On load, the JS retrieves the target node via getElementById('gradientFlowText'), splits the string character by character (split('')), and re-injects each letter into a <span> with an inline style: animation-delay: index × 0.2 s. The result is written in one shot via innerHTML. The HTML can also be pre-rendered server-side with the same attributes for immediate display before JS runs.
The gradientFlowLetter keyframe (duration 3 s, easing ease-in-out, infinite) animates only the color property: it starts from the resting gray #71717a, peaks at vivid fuchsia #d946ef at the midpoint (50%), then returns. A text-shadow glow (rgba(217, 70, 239, 0.5) 0 0 20px) lights up simultaneously at the peak to amplify the letter's brightness without affecting layout.
Because of the staggered delays, the color peak visits each letter 0.2 s apart. Since all animations share the same duration (3 s), their phases are permanently offset — some letters are rising while others are falling at any given moment, creating the illusion of a continuous wave traveling through the word without ever stopping.
The Replay button clears the container's innerHTML, waits 50 ms (to force a layout recalculation and reset all animations to zero), then re-injects the spans by calling initGradientFlow() — relaunching the wave from the first letter.
Accessibility
- prefers-reduced-motion: not handled in the provided code — the animation loops indefinitely regardless of the OS preference. In production, add
@media (prefers-reduced-motion: reduce) { .text-gradient-letter span { animation: none; color: #d946ef; } }to freeze letters on the peak color. - The text is real DOM content: letters remain readable by screen readers without additional attributes.
- Resting contrast —
#71717aon#0a0a0f: ratio ≈ 4.6:1 (passes WCAG AA ≥ 4.5:1 for normal text). At fuchsia peak#d946ef: ratio ≈ 7.3:1 (passes WCAG AAA). - The Replay button is a native
<button>, keyboard-focusable (Tab) and activatable via Enter/Space. - No
aria-labelorroleis set on the container: add them if the element carries semantic meaning (e.g.role="img" aria-label="Animated text: GRADIENT").
Browser compatibility
Built on native CSS animations and vanilla innerHTML — supported in all modern browsers. Zero external dependencies.
If CSS animations are not supported, the text displays in resting color (<code>#71717a</code>) — no JS errors, content stays readable.
The code
HTML structure to paste into your page (CSS + JS available with a premium account):
<div class="demo-preview">
<span class="demo-text text-gradient-letter" id="gradientFlowText">
<!-- Spans generated by initGradientFlow() or pre-rendered -->
<span style="animation-delay: 0s">G</span>
<span style="animation-delay: 0.2s">R</span>
<span style="animation-delay: 0.4s">A</span>
<span style="animation-delay: 0.6s">D</span>
<span style="animation-delay: 0.8s">I</span>
<span style="animation-delay: 1s">E</span>
<span style="animation-delay: 1.2s">N</span>
<span style="animation-delay: 1.4s">T</span>
</span>
<button class="replay-btn" onclick="replayGradientFlow()">Replay</button>
</div>
Full HTML + CSS + JS, copy-paste ready — with hundreds of premium effects.
Customize
Options passed to the API or data-* attributes:
| Option / property | Default | Effect |
|---|---|---|
| color peak (keyframe gradientFlowLetter, 50%) | #d946ef | Color at the wave peak. Replace with any CSS color to match your brand: indigo, gold, cyan, coral red… |
| text-shadow glow (keyframe gradientFlowLetter, 50%) | rgba(217, 70, 239, .5) 0 0 20px | Luminous halo around the letter at peak. Increase the radius (30px) or opacity for a more dramatic flare. Set to none to disable. |
| color rest (keyframe gradientFlowLetter, 0% & 100%) | #71717a | Base color outside the animation. Adapt to your background: off-white on a light surface, dark blue-gray for a premium look. |
| animation duration (.text-gradient-letter span) | 3s | Full cycle duration per letter. Shorten to 1.5 s for a lively wave, lengthen to 5 s for a contemplative rhythm. |
| stagger multiplier: i * 0.2 (JS initGradientFlow) | 0.2 | Delay in seconds between two consecutive letters. At 0.08 the wave is tight and fast; at 0.4 it is broad and solemn. Adjust to the word length. |
| font-size (.demo-text) | 2.5rem | Font size. Use 1 rem for an inline UI label, 5–6 rem for a large full-screen hero. |
| font-weight (.demo-text) | 800 | Font weight. Heavy weights (700–900) accentuate the brightness contrast between the resting and peak colors. |
| letter-spacing (.demo-text) | -.02em | Letter spacing. A positive value (0.05–0.12 em) adds visual breathing room and makes per-letter color transitions more distinct. |
FAQ
@keyframes, animation-delay) and about twenty lines of JS (innerHTML, split, map). Zero npm dependencies. Copy the HTML, CSS, and JS and it's ready. Compatible with React, Vue, and Svelte: generate the <span style="animation-delay: Xs"> elements in your component and apply the text-gradient-letter class.text constant in initGradientFlow() (e.g. const text = 'DESIGN') — or generate the spans server-side or in your framework. Each span must have style="animation-delay: Xs" with X = index × 0.2. Adjust the multiplier to the word length to keep a consistent spread.text-gradient-letter class — the number of instances is unlimited. On the JS side, the function targets a unique id (gradientFlowText) for replay; create elements with distinct ids and call the initialization logic on each one individually.