← Back to gallery
CSSFeatured

Gradient Text Sweep

A narrow highlight band sweeps across live headline text via background-clip + an explicit two-axis background-size, with a static fallback color for engines without clip support. Three variants: a wide launch headline, a tight command label, and a slower editorial kicker.

gradient-textbackground-clipbackground-sizebackground-positionsupports-fallbacktext-shadowprefers-reduced-motion

Gradient Text / Background Sweep

Gradient Text Sweep

Live text keeps a readable fallback color, then uses background-clip: text with explicit two-axis background-size so the highlight band can pass across long headlines without layout shift.

Motion Library

Wide hero phrase

Launch Headline

A broad cyan-white band moves through a large product headline while the fallback color stays legible before clip support applies. Use for landing / catalog headers that want one controlled brightness pass instead of constant rainbow motion.

  • hero headline
  • background-clip
  • fallback color

Deploy Preview

Compact product UI

Command Label

A shorter sweep keeps utility labels crisp and avoids extra padding around the text box so the gradient tracks the glyphs tightly. Good for empty states and command surfaces where text should feel active without becoming decorative.

  • utility label
  • tight box
  • amber + cyan

Reusable CSS Motion

Longer scanning line

Editorial Kicker

A slower diagonal pass leaves enough dwell time for longer text to stay readable while the shine crosses the full phrase. Wider band-width avoids visible jumps when the background-position wraps.

  • long phrase
  • slow pass
  • violet + cyan

Sweep inspector

Launch Headline

Motion Library

  • hero headline
  • background-clip
  • fallback color

A broad cyan-white band moves through a large product headline while the fallback color stays legible before clip support applies. Use for landing / catalog headers that want one controlled brightness pass instead of constant rainbow motion.

Helped you ship something? 🐟 Send my cat a churu

.gradient-text {
  color: #dbeafe;
}

@supports ((background-clip: text) or (-webkit-background-clip: text)) {
  .gradient-text {
    background-image: linear-gradient(104deg, #9fb2d8 0%, #e2e8f0 36%, #67e8f9 46%, #ffffff 50%, #67e8f9 54%, #e2e8f0 64%, #9fb2d8 100%);
    background-size: 260% 100%;
    background-position: 0% 50%;
    background-clip: text;
    -webkit-background-clip: text;
    color: transparent;
    -webkit-text-fill-color: transparent;
    text-shadow: 0 0 16px rgba(103, 232, 249, 0.34);
    animation: gradientTextSweep 4.8s linear infinite;
  }
}

@keyframes gradientTextSweep {
  from { background-position: 0% 50%; }
  to   { background-position: 100% 50%; }
}

@media (prefers-reduced-motion: reduce) {
  .gradient-text {
    animation: none;
    background-position: 55% 50%;
  }
}

How to make this

A CSS gradient text sweep keeps a real fallback color, clips an oversized linear-gradient to the text inside @supports, then animates background-position across the glyphs.

html
1<p class="gradient-sweep">Motion Library</p> <style>.gradient-sweep {  max-width: 100%;  margin: 0;7  color: #dbeafe;  font: 850 clamp(2rem, 8vw, 4rem)/1.05 sans-serif;  text-align: center;}11@supports ((background-clip: text) or (-webkit-background-clip: text)) {  .gradient-sweep {    background-image: linear-gradient(      104deg,      #9fb2d8 0%,      #e2e8f0 36%,      #67e8f9 46%,      #ffffff 50%,      #67e8f9 54%,      #e2e8f0 64%,      #9fb2d8 100%    );23    background-size: 260% 100%;    background-position: 0% 50%;    background-clip: text;    -webkit-background-clip: text;    color: transparent;28    -webkit-text-fill-color: transparent;    text-shadow: 0 0 16px rgba(103, 232, 249, .34);    animation: gradient-text-sweep-pass 4.8s linear infinite;  }}@keyframes gradient-text-sweep-pass {  from { background-position: 0% 50%; }  to { background-position: 100% 50%; }}37@media (prefers-reduced-motion: reduce) {  .gradient-sweep {    animation: none;    background-position: 55% 50%;  }}</style>

Annotated snippet

  1. Line 1Keep the text as a real text node. The gradient is paint, not an image replacement, so the headline remains selectable, searchable, and readable before enhanced clipping applies.
  2. Line 7The fallback color is set before @supports. If background-clip: text is unsupported, the text stays visible instead of becoming transparent.
    PitfallWhy did my gradient text disappear?

    Transparent text was probably applied before confirming background-clip: text support. Set a normal color first, then put background clipping, color: transparent, and -webkit-text-fill-color: transparent inside an @supports block.

  3. Line 11The clipping rules are gated together. Only browsers that support text background clipping get transparent fill and the moving gradient.

    Both elements have the same gradient + color: transparent. Drop background-clip: text and the gradient stays a rectangle while the now-invisible text is hidden — "where did my headline go?". Add the clip and the gradient pours into the letter shapes.

    PitfallWhy did my gradient text disappear?

    Transparent text was probably applied before confirming background-clip: text support. Set a normal color first, then put background clipping, color: transparent, and -webkit-text-fill-color: transparent inside an @supports block.

  4. Line 23background-size: 260% creates a wider gradient canvas than the text box, giving the bright band room to enter, cross, and leave.

    Same background-position 0% → 100% animation on both. With background-size: 100% the gradient barely shifts because there is no off-canvas runway; with 260% the highlight band visibly sweeps across the glyphs.

    PitfallWhy does my gradient sweep look like a static rainbow?

    The gradient canvas is likely too narrow. Use a background-size wider than the text, such as 220% to 320% on the inline axis, and animate background-position across that larger canvas. The bright band needs off-screen runway.

  5. Line 28-webkit-text-fill-color is still needed for Safari/WebKit text clipping. Pair it with color: transparent so both WebKit and non-WebKit engines agree.
    PitfallWhich browsers need -webkit-text-fill-color for gradient text?

    Safari and other WebKit-based browsers still need -webkit-background-clip: text and -webkit-text-fill-color: transparent for reliable clipped gradient text. Keep the unprefixed properties too, and test fallback visibility.

  6. Line 37Reduced motion freezes the highlight at a stable readable position. The fallback text color still protects unsupported or forced-color contexts.
    PitfallHow should gradient text handle prefers-reduced-motion?

    Stop the background-position animation and hold a stable highlight position. Do not remove the text or make it transparent-only. Reduced motion should leave the headline readable with the same semantic text content.

Other pitfalls

Is animating gradient text performant?
Animating background-position is paint work, not a pure compositor transform. It is fine for a small number of headlines, but avoid applying looping gradient text to long paragraphs or many list items. Keep glow and filter effects restrained.
Advanced

Layer a second counter-direction sweep so two highlights pass through the letters

Same headline, same background-clip: text, same 4.8s linear cycle. BEFORE paints a single cool-toned gradient and slides its background-position 0→100% — clean but predictable. AFTER stacks a second warm-toned highlight gradient (76deg, narrow band) on top of the base gradient and animates them in opposite directions in the same keyframe (the warm band travels 100%→-100% while the base travels 0%→100%). They cross at the headline center, producing a brighter mid-word crossover. Same background-clip + position animation, just multi-layer.

View explanation and full code36 lines

The base recipe paints ONE gradient on the text and slides its background-position. Production headline shimmers (Apple keynote titles, Vercel marketing hero) stack TWO gradients in the same background-image (comma-separated) with their own background-size and background-position values, then animate both positions in one keyframe — each layer sweeps independently. Same background-clip: text, same `:supports` gate, same animation property — just multi-layer instead of single-layer. The two highlights cross mid-word and produce a brighter crossover moment without adding any new selectors or breaking the fallback color.

Append these rules inside the <style> block from the base snippet above.

css
/* Advanced: layered counter-direction sweeps — extends the base recipe. */@supports ((background-clip: text) or (-webkit-background-clip: text)) {  .gradient-sweep {    background-image:      linear-gradient(        76deg,        transparent 38%,        rgba(253, 224, 71, .88) 48%,        #ffffff 50%,        rgba(253, 224, 71, .88) 52%,        transparent 62%      ),      linear-gradient(        104deg,        #9fb2d8 0%,        #e2e8f0 36%,        #67e8f9 46%,        #ffffff 50%,        #67e8f9 54%,        #e2e8f0 64%,        #9fb2d8 100%      );    background-size: 220% 100%, 260% 100%;    background-position: 100% 50%, 0% 50%;    animation: gradient-text-sweep-layered 4.8s linear infinite;  }}@keyframes gradient-text-sweep-layered {  from { background-position: 100% 50%, 0% 50%; }  to   { background-position: -100% 50%, 100% 50%; }}@media (prefers-reduced-motion: reduce) {  .gradient-sweep {    background-position: 50% 50%, 55% 50%;  }}

Notes

Overview

A gradient text sweep paints a moving highlight band through headline text via background-clip: text on an oversized background gradient. The text node stays live in the DOM — selectable, copyable, AT-readable — while a narrow bright band crosses the glyph shapes without any per-letter spans or canvas hacks. Behind a @supports guard, browsers without background-clip-text fall through to a solid fallback color so nothing renders as invisible.

When to use it

Reach for gradient text sweeps on launch headlines, single-line CTAs, marquee strap lines — anywhere one prominent string is the visual hero. Skip it for paragraph copy; the sweep is beautiful at 64px and unreadable at 14px. Skip it when the rest of the page is already loud — a sweep next to a gooey blob or particle burst reads as a third competing element, not a refined accent.

How it works

Set background-image on the text to a linear gradient with explicit color stops including the bright sweep band, then set background-size larger than 100% on the x-axis (e.g. 260% 100%) so the gradient is wider than the text. Clip the background to the glyphs with background-clip: text + -webkit-background-clip: text and set color: transparent + -webkit-text-fill-color: transparent. Now animate background-position from 0% 50% to 100% 50% — the sweep moves across the oversized gradient and the visible part inside the glyphs shifts in lockstep.

Production gotchas

The @supports guard is non-negotiable — omit it and Firefox versions without the property render invisible text (color transparent + no clip = nothing). Animating background-position as a string can confuse certain browsers’ transition interpolation; if you see janky stepping, switch to a keyframe that interpolates a --bg-pos custom property via @property instead. Drop shadows behind clipped text render as the shadow of the glyphs, not the gradient — for a colored glow behind the sweep use filter: drop-shadow, not text-shadow.

Accessibility

The text node remains real DOM content so screen readers and search engines see the string normally. The sweep is purely decorative; on prefers-reduced-motion: reduce the animation pauses with the gradient pinned at a middle position so the headline still reads as gradient-clipped without the moving band. Always verify the fallback color (and the gradient at its rest position) meets WCAG AA contrast against the surface behind it.

References

Implementation depth

The live text node is the product; the moving gradient is just paint. Use background-clip: text with a supports guard, then animate background-position across an oversized gradient so the glyph outlines remain selectable.

The fallback color matters because transparent text without clipping becomes invisible. Verify contrast for the fallback and the paused reduced-motion frame, especially when the sweep sits over a busy hero background.