Text Animations

Gradient Shine Text

A flowing gradient text with a periodic shine sweep on top — pure CSS keyframes, adapting to light and dark themes.

Bring this into your project

Run this command in your project folder. The CLI adds the source and dependencies; then follow the usage example below.

npx webberui@latest add gradient-shine-text.en

New project or installation trouble? Start here →

Gradient Shine Text is a React gradient text animation built with plain CSS @keyframes. It uses background-clip: text to flow a gradient through the letters and adds a highlight that sweeps across on a cycle, with no Motion or other animation library.

Playground

Tune the props live — the code snippet updates as you go, so you can dial in the look you want before copying it.

6
Active edited usageDefault props
<GradientShineText/>

The complete example includes the preview layout and data. Install the component first, then paste this file into your project.

When to use

  • Highlighting just the product name or one key phrase in a homepage hero headline.
  • Headlines on feature announcements or release pages.
  • The badge or plan name for the recommended tier on a pricing page.
  • Short taglines on event countdowns or campaign visuals.

Installation

npx webberui@latest add https://webberui.com/r/gradient-shine-text.en.json

Or, once registries are configured in components.json, install it as @webberui/gradient-shine-text.

Usage

import { GradientShineText } from "@/components/ui/gradient-shine-text";

<GradientShineText
  text="Beautiful by default."
  className="text-4xl font-bold"
/>

// Custom gradient colors and cycle, or turn the shine off
<GradientShineText colors={["#0ea5e9", "#34d399"]} duration={8} shine={false}>
  The gradient flows, and it supports Chinese too.
</GradientShineText>

Examples

Highlight part of a headline

Use a regular h1 and wrap only the words you want to emphasize; the component renders a span by default, so the heading semantics stay intact.

import { GradientShineText } from "@/components/ui/gradient-shine-text";

<h1 className="text-4xl font-bold tracking-tight md:text-6xl">
  Manage all customer feedback in <GradientShineText>one workspace</GradientShineText>
</h1>

Render as a heading with brand colors

Set as to h2 or any other tag. List colors in order and the component appends the first color at the end so the loop has no seam. A larger duration slows the flow.

<GradientShineText
  as="h2"
  text="2026 product updates"
  colors={["#0ea5e9", "#6366f1", "#22c55e"]}
  duration={10}
  className="text-3xl font-semibold"
/>

Gradient without the shine

shine={false} keeps only the slow-moving gradient, which works better on small labels where a highlight would look busy.

<GradientShineText shine={false} duration={12} className="text-xs font-semibold uppercase tracking-wider">
  Recommended
</GradientShineText>

Props

PropTypeDefaultDescription
textstring—The text to render (use either this or children)
childrenReactNode—Custom content, which takes precedence over text
colorsstring[]built-in three-color gradientGradient colors in order; the first is appended to the end automatically for a seamless loop
durationnumber6One flow cycle (seconds); the shine sweeps once early in each cycle
shinebooleantrueWhether to overlay a periodically sweeping highlight band
asReact.ElementType"span"The element tag to render
classNamestring—Extra styles (set font size, weight, and so on here)

How it works

  • Pure CSS animation: the @keyframes are injected by an inline <style> inside the component, so installing it into any project requires no changes to the Tailwind config or the global stylesheet, and there is no hydration flash
  • Seamless loop: the flowing gradient automatically matches its first and last color, and each cycle offsets by exactly one tile width, so it loops without a seam under background-repeat
  • Shine layer: a second, no-repeat narrow highlight band sits on top of the gradient, sweeping across during the first 45% of each cycle and parking off-screen the rest of the time
  • Light and dark modes: the default colors are defined as --wb-gst-* CSS variables (wrapped in :where to keep specificity low), which automatically switch to a brighter set under .dark; colors can also override them entirely

Accessibility

  • The text is real DOM text (background-clip: text only affects the coloring), so screen readers announce it normally and it remains searchable and selectable
  • When the user has "reduce motion" enabled at the system level, the animation stops and a static gradient is shown (the shine parks off-screen and stays invisible)

FAQ

Do I need to change my Tailwind config or global CSS?

No. The @keyframes and default color variables are injected by an inline <style> inside the component, and the only dependencies are clsx and tailwind-merge. Put font size and weight on className.

Does it affect SEO or screen readers?

No. The text is real DOM text; background-clip: text only changes how it is painted, so search engines and screen readers read it normally and users can select and copy it. Use as="h1" or another tag to keep heading semantics.

How does dark mode switch colors?

Without colors, the default palette comes from --wb-gst-* CSS variables and switches to brighter colors when an ancestor has the .dark class. Sites that rely only on prefers-color-scheme without a .dark class will not get the dark palette, so pass colors instead.

Does it work with the Next.js App Router?

Yes. The source starts with "use client", so import it from a Server Component page as usual. The animation runs entirely in CSS, with no JavaScript that starts after mount.

What happens with reduced motion?

With "reduce motion" enabled, a CSS media query removes the animation, the text keeps a static gradient, and the shine stays offscreen.