Shimmer

A CSS utility that sweeps an animated highlight across text for live status and streaming states, with no component required.

shimmer paints text with an animated highlight that loops across it — the canonical "Generating response…" / "Thinking…" affordance for streaming or in-progress states. It's pure CSS: the text is rendered with background-clip: text and a gradient highlight sweeps over it in a seamless loop.

The highlight is derived from the element's own currentColor via relative color syntax, so it adapts to any text color with no configuration, and brightens automatically in dark mode.

Directly inspired by shadcn's shimmer utility, adapted for Cubby UI and re-tuned to read well against its color tokens in light and dark.

Generating response…

Because the highlight brightens the text, the effect reads best on dimmed text such as text-muted-foreground — there's little headroom to brighten text that's already near-white (e.g. text-foreground in dark mode). This matches the typical use: a muted status line.

Installation

Like Scroll Fade, shimmer relies on @property to animate the highlight, so it ships as a CSS file rather than through the registry's CSS channel. Add it, then import it once in your global CSS:

Usage

Add shimmer to any text element. The highlight is built from the text color, so it works on text-muted-foreground or a brand color with no extra setup.

It composes with any component that renders text — for example, a status label inside a button or badge while an action is in flight.

Classes

Every variant tab below has a Code tab with the exact markup. Reference for the full surface:

ClassEffect
shimmerSweep an animated highlight across the text
shimmer-oncePlay a single sweep instead of looping
shimmer-reverseSweep in the opposite direction
shimmer-noneTurn the effect off (works responsively, e.g. md:shimmer-none)
shimmer-color-<color>Set the highlight color (accepts /<opacity> and arbitrary values)
shimmer-duration-<ms>One sweep duration in milliseconds (default 2000)
shimmer-spread-<n>Width of the highlight band on the spacing scale (also arbitrary lengths)
shimmer-angle-<deg>Tilt of the highlight band in degrees (default 20)

Color

The highlight defaults to a derivative of the text color. Use shimmer-color-<color> to set it explicitly — it accepts theme colors (with an optional /<opacity> modifier) or any arbitrary value like shimmer-color-[#22c55e].

Generating response…

Generating response…

Generating response…

Duration

Use shimmer-duration-<ms> to set how long one sweep takes, in milliseconds. The default is 2000.

Default · 2s

Faster · 1s

Slower · 3.5s

Spread

Use shimmer-spread-<n> to set the width of the highlight band on the spacing scale, or an arbitrary length like shimmer-spread-[3rem]. The default is calc(3ch + 40px) — a fixed base plus a 3ch term that scales with the font size.

Default band

Wider band

Narrow band

Angle

Use shimmer-angle-<deg> to set the tilt of the highlight band in degrees. The default is 20.

Default · 20°

Flat · 0°

Steeper · 45°

Play Once

Use shimmer-once for a single sweep instead of a loop — useful as a reveal when streaming completes. Pair it with shimmer-duration-<ms> to control how long the reveal takes. (Press Replay to see it again.)

Response generated.

Disabling

Use shimmer-none to render the text normally. It works in any class order, so the typical use is responsive or stateful — shimmer while loading, solid once resolved:

Shimmer on

Shimmer off

Reverse

Use shimmer-reverse to sweep the highlight in the opposite direction. In RTL layouts the sweep already follows the reading direction, so you only need this to flip it manually.

Fallback & reduced motion

The shimmer uses modern color features (relative color syntax and color-mix()), available in all current browsers. In older browsers without support the highlight is dropped and the text may render transparent — apply it conditionally with a supports-* variant if you target those:

When the user prefers reduced motion, the animation is disabled automatically and the text renders normally — nothing to configure.