Text Shimmer Effect

Text Shimmer Effect

The following shimmer effect is built for shadcn/ui-based projects. Installation, usage, and examples are given below.

Basic Shimmer Effect

shimmer-demo.tsx
import { ShimmerText } from "@/components/ui/shimmer-text";

export function ShimmerDemo() {

  return (
    <div className="flex justify-center items-center py-10 text-center">
      <ShimmerText
      	as={"h1"}
      	className="text-sm sm:text-base lg:text-xl font-medium font-mono"
      	textColor="var(--muted-foreground)"
      	shimmerColor="var(--foreground)"
      	duration={2000}
      	interval={500}
     >
      	Steve Rogers Will Return in Avengers: Doomsday
     </ShimmerText>
    </div>
  );
}

Installation

Make sure you have set up a shadcn/ui project and have the cn helper function. If not, create one by asking your favourite LLM.

Paste the following code into your project.

components/ui/shimmer-text.tsx

import type * as React from "react"
import { cn } from "@/lib/utils";


type Ease =
    | React.CSSProperties["animationTimingFunction"]
    | number[]; // for cubic-bezier

function resolveEase(ease: Ease): string {
    if (Array.isArray(ease)) {
        return `cubic-bezier(${ease.join(",")})`;
    }
    return ease ?? "linear";
}

type ShimmerProps<T extends React.ElementType> = {
    as?: T;
    children?: React.ReactNode;

    /**
     * Easing function applied to the shimmer sweep.
     * Accepts a CSS timing keyword or a 4-number cubic-bezier array.
     * @example
     * ease="linear"
     * @example
     * ease={[0.79, 0.54, 0.23, 0.68]}
     */
    ease?: Ease;

    /**
     * Duration of a single shimmer sweep, in milliseconds.
     * @default 4000
     */
    duration?: number;

    /**
     * Pause between sweeps, in milliseconds.
     * @default 800
     */
    interval?: number;

    /**
     * Accepts any CSS `animation-iteration-count` value (`"infinite"`, a number, etc.).
     * @default "infinite"
     */
    iteration?: React.CSSProperties["animationIterationCount"];

    /**
     * Base text color.
     * Accepts any CSS `<color>` value.
     *
     * @example
     * textColor="hsl(var(--muted-foreground))"
     */
    textColor?: React.CSSProperties["backgroundColor"];

    /**
     * Color of the shimmer highlight that sweeps across the text.
     * Accepts any CSS `<color>` value.
     * @default "var(--foreground)"
     *
     * @example
     * shimmerColor="#ffffff"
     */
    shimmerColor?: React.CSSProperties["backgroundColor"];

    /**
     * Half-width of the shimmer highlight band, as a CSS length.
     * @default "50px"
     *
     * @example
     * shimmerWidth="80px"
     */
    shimmerWidth?: string;
} & React.ComponentPropsWithoutRef<T>;

/**
 * @template T - The element type to render as (defaults to `"span"`).
 *
 * @example
 * // Basic usage
 * <Shimmer>Loading…</Shimmer>
 *
 * @example
 * // Heading with custom colors and speed
 * <Shimmer
 *   as="h1"
 *   duration={2000}
 *   interval={400}
 *   shimmerColor="#a855f7"
 *   textColor="hsl(var(--muted-foreground))"
 * >
 *   Welcome back
 * </Shimmer>
 *
 * @example
 * // Link that shimmers (href is inferred from as="a")
 * <Shimmer as="a" href="/dashboard" shimmerWidth="80px">
 *   Go to dashboard
 * </Shimmer>
 */
export function ShimmerText<T extends React.ElementType>({
    // Animation Props
    duration = 4000, interval = 800,
    iteration = "infinite", ease = [0.79, 0.54, 0.23, 0.68],
    textColor, shimmerColor, shimmerWidth,

    // Element Props
    as, children, className, style, ...props
}: ShimmerProps<T>) {
    const Comp = as ?? "span"
    const total = duration + interval; // In milliseconds
    const intervalPct = ((interval / total) * 100).toFixed(2);
    const EASE = resolveEase(ease)

    return (
        <>
            <style>
                {`
                    @keyframes shimmerrun {
                        0%  { 
                            background-position: 100% center; 
                        } 
                        ${intervalPct}%  { 
                            background-position: 100% center; 
                            animation-timing-function: ${EASE};
                        } 
                        100%  { 
                            background-position: 0% center; 
                        } 
                    }
                `}
            </style>

            <Comp
                className={cn("text-transparent bg-clip-text bg-no-repeat bg-muted-foreground", className)}
                style={{
                    ...style,
                    "--shimmer-width": shimmerWidth ?? "50px",
                    "--shimmer-color": shimmerColor ?? "var(--foreground)",
                    backgroundSize: "250% 100%",
                    backgroundImage: "linear-gradient(90deg, transparent calc(50% - var(--shimmer-width)), var(--shimmer-color) , transparent calc(50% + var(--shimmer-width)))",
                    animation: `shimmerrun ${total}ms linear ${iteration}`,
                    backgroundColor: textColor
                } as React.CSSProperties}
                {...props}
            >
                {children}
            </Comp>
        </>
    );
}

Make sure the import paths match your project's structure.

Props & Usage

All props in this text shimmer effect are self-explanatory. However, the table below gives an overview of them and demonstrates how to change colors.

PropTypeDefaultDescription
asElementTypespanThe element or component to render as.
childrenReactNode—The text content to apply the shimmer effect to.
easestring | number[]—CSS timing function keyword (e.g. "linear", "ease-in-out") or a 4-number cubic-bezier array.
duration in msnumber4000Duration of a single shimmer sweep, in milliseconds.
interval in msnumber800Pause between sweeps, in milliseconds.
iterationstring | number"infinite"Accepts any CSS animation-iteration-count value.
textColorstring—Base text color. Accepts any CSS color value.
shimmerColorstring"var(--foreground)"Color of the shimmer highlight that sweeps across the text. Accepts any CSS color value.
shimmerWidthstring"50px"Half-width of the shimmer highlight band, as a CSS length.

Examples

You can use the textColor property or bg-[...] className of Tailwind CSS to change the text color

shimmer-demo.tsx
import { ShimmerText } from "@/components/ui/shimmer-text";

export function ShimmerDemo() {

  return (
    <div className="flex justify-center items-center py-10 text-center">
      <ShimmerText
      as="h1"
      className="text-sm sm:text-base lg:text-xl font-medium font-mono"
      textColor="hsl(240 5% 35%)"
      shimmerColor="hsl(240 100% 80%)"
      duration={2000}
      interval={500}
    >
      Thor Will Return in Avengers: Doomsday
    </ShimmerText>
    </div>
  );
}

And use the shimmerColor property to change the color of animating shimmer.

shimmer-demo.tsx
import { ShimmerText } from "@/components/ui/shimmer-text";

export function ShimmerDemo() {

  return (
    <div className="flex justify-center items-center py-10 text-center">
    <ShimmerText
      as="h1"
      className="text-sm sm:text-base lg:text-xl font-medium font-mono"
      textColor="hsl(160 10% 30%)"
      shimmerColor="hsl(155 80% 55%)"
      duration={2000}
      interval={500}
    >
      Tony Will Return in Avengers: Doomsday
    </ShimmerText>
    </div>
  );
}

Last Update: 12 May 2026 at 10:40 AM