Skip to content
jjswnth/ui

Text

Text Shimmer

A light sweep across any text, driven entirely by a CSS gradient animation.

Shipping something new

analyzing dependencies…

Installation

  1. 1. Install the dependencies.

    terminal
    npm install clsx tailwind-merge
  2. 2. Add the cn helper, if you don't already have it.

    lib/utils.ts
    import { clsx, type ClassValue } from "clsx";
    import { twMerge } from "tailwind-merge";
    
    export function cn(...inputs: ClassValue[]) {
      return twMerge(clsx(inputs));
    }
  3. 3. Copy the component into your project.

    components/ui/text-shimmer.tsx
    "use client";
    
    import { createElement, type ElementType } from "react";
    import { cn } from "@/lib/utils";
    
    type TextShimmerProps = {
      children: string;
      className?: string;
      /** Tag to render. Defaults to a span. */
      as?: ElementType;
      /** Seconds for one full sweep. */
      duration?: number;
      /** Width of the highlight band, as a share of the text width. */
      spread?: number;
    };
    
    export function TextShimmer({
      children,
      className,
      as = "span",
      duration = 2.4,
      spread = 0.35,
    }: TextShimmerProps) {
      return createElement(
        as,
        {
          className: cn(
            "inline-block bg-clip-text text-transparent [background-size:200%_100%] motion-safe:animate-shimmer",
            className,
          ),
          style: {
            backgroundImage: `linear-gradient(90deg,
              color-mix(in oklab, currentColor 35%, transparent) 0%,
              color-mix(in oklab, currentColor 35%, transparent) ${50 - spread * 50}%,
              currentColor 50%,
              color-mix(in oklab, currentColor 35%, transparent) ${50 + spread * 50}%,
              color-mix(in oklab, currentColor 35%, transparent) 100%)`,
            animationDuration: `${duration}s`,
          },
        },
        children,
      );
    }

Props

PropTypeDefaultDescription
childrenstringText to animate.
asElementType"span"Tag to render.
durationnumber2.4Seconds for one full sweep.
spreadnumber0.35Width of the highlight band, as a share of the text width.
classNamestringMerged onto the rendered element.