Text Effect Configurable

FREE

A configurable text effect for elements

Demo

Animate your ideas with CSS
Exclusive Launch 50% offspots left: 0 / 50
3D Cube - happy face3D Cube - Happy Face
$39.99

$19.99

Payment once and get lifetime access
Access to all animations
All updates
All animations
No subscriptions

Installation

1

Copy and paste the following code into your project.

Add this component text-effect-configurable.tsx to your project.

text-effect-configurable.tsx
import type { ReactNode, ElementType } from "react";
import { cn } from "~/lib/utils";

interface TextEffectConfigurableProps {
  children: ReactNode;
  as?: ElementType;
  effect?: "fade" | "blur" | "slide" | "scale" | "rotate";
  delay?: number;
  duration?: number;
  className?: string;
}

// Function to extract text from React children recursively
function extractTextFromChildren(children: ReactNode): string {
  if (typeof children === "string") {
    return children;
  }

  if (typeof children === "number") {
    return String(children);
  }

  if (Array.isArray(children)) {
    return children.map(extractTextFromChildren).join("");
  }

  if (children && typeof children === "object" && "props" in children) {
    // If it's a React element, try to extract text from its children
    return extractTextFromChildren((children as { props: { children: ReactNode } }).props.children);
  }

  return "";
}

export function TextEffectConfigurable({
  children,
  as: Component = "div",
  effect = "fade",
  delay = 0.05,
  duration = 0.6,
  className = "",
}: TextEffectConfigurableProps) {
  // Convert children to string using our extraction function
  const text = extractTextFromChildren(children);

  const getAnimationClass = () => {
    switch (effect) {
      case "blur":
        return "animate-blur-in";
      case "slide":
        return "animate-slide-up";
      case "scale":
        return "animate-scale-in";
      case "rotate":
        return "animate-rotate-in";
      default:
        return "animate-fade-in";
    }
  };

  const getInitialClasses = () => {
    switch (effect) {
      case "blur":
        return "blur-sm opacity-0";
      case "slide":
        return "opacity-0 translate-y-0";
      case "scale":
        return "opacity-0 scale-none";
      case "rotate":
        return "opacity-0";
      default:
        return "opacity-0";
    }
  };

  const animatedContent = text.split("").map((char, index) => (
    <span
      key={index}
      className={cn("inline-block", getInitialClasses(), getAnimationClass())}
      style={{
        animationDelay: `${index * delay}s`,
        animationDuration: `${duration}s`,
        animationFillMode: "forwards",
      }}
    >
      {char === " " ? "\u00A0" : char}
    </span>
  ));

  const renderElement = () => {
    const commonProps = {
      className: cn("text-3xl font-bold text-white", className),
    };

    switch (Component) {
      case "h1":
        return <h1 {...commonProps}>{animatedContent}</h1>;
      case "h2":
        return <h2 {...commonProps}>{animatedContent}</h2>;
      case "h3":
        return <h3 {...commonProps}>{animatedContent}</h3>;
      case "h4":
        return <h4 {...commonProps}>{animatedContent}</h4>;
      case "h5":
        return <h5 {...commonProps}>{animatedContent}</h5>;
      case "h6":
        return <h6 {...commonProps}>{animatedContent}</h6>;
      case "p":
        return <p {...commonProps}>{animatedContent}</p>;
      case "span":
        return <span {...commonProps}>{animatedContent}</span>;
      case "blockquote":
        return <blockquote {...commonProps}>{animatedContent}</blockquote>;
      case "strong":
        return <strong {...commonProps}>{animatedContent}</strong>;
      case "em":
        return <em {...commonProps}>{animatedContent}</em>;
      default:
        return <div {...commonProps}>{animatedContent}</div>;
    }
  };

  return renderElement();
}
2

Add the following keyframes and animations to your project.

global.css

@layer utilities {
 // START HERE ------------------------------------------------------------
  @keyframes fade-in {
    from {
      opacity: 0;
    }
    to {
      opacity: 1;
    }
  }

  .animate-fade-in {
    animation: fade-in 0.6s ease-out forwards;
  }

  @keyframes blur-in {
    from {
      opacity: 0;
      filter: blur(12px);
    }
    to {
      opacity: 1;
      filter: blur(0px);
    }
  }

  .animate-blur-in {
    animation: blur-in 0.8s ease-out forwards;
  }

  @keyframes slide-in {
    from {
      opacity: 0;
      transform: translateY(20px);
    }
    to {
      opacity: 1;
      transform: translateY(0);
    }
  }

  .animate-slide-in {
    animation: slide-in 0.6s ease-out forwards;
  }

  @keyframes scale-in {
    from {
      opacity: 0;
      transform: scale(0);
    }
    to {
      opacity: 1;
      transform: scale(1);
    }
  }

  .animate-scale-in {
    animation: scale-in 0.5s cubic-bezier(0.175, 0.885, 0.32, 1.275) forwards;
  }

  @keyframes rotate-in {
    from {
      opacity: 0;
      transform: rotate(-180deg) scale(0);
    }
    to {
      opacity: 1;
      transform: rotate(0deg) scale(1);
    }
  }

  .animate-rotate-in {
    animation: rotate-in 0.8s ease-out forwards;
  }
// END HERE ------------------------------------------------------------
}
3

Start using the component TextEffectConfigurable in your project.

Usage Example


// Basic character-by-character animation
<TextEffectConfigurable effect="slide" delay={0.1} duration={0.8}>
  Animate your ideas with CSS
</TextEffectConfigurable>
// ------------------------------------------------------------
// Fast scale animation
<TextEffectConfigurable 
  effect="scale" 
  delay={0.03} 
  duration={0.4}
  as="h1"
  className="text-4xl font-bold"
>
  Quick Animation
</TextEffectConfigurable>
// ------------------------------------------------------------
// Slow fade with custom styling
<TextEffectConfigurable 
  effect="fade" 
  delay={0.15} 
  duration={1.2}
  className="text-blue-400"
>
  Elegant and Slow
</TextEffectConfigurable>

Properties

The TextEffectConfigurable component accepts the following props:

PropertyTypeDefaultDescription
childrenReactNode-The text content to animate
asElementType"div"The HTML element to render
effect"fade" | "blur" | "slide" | "scale" | "rotate""fade"The type of animation
delaynumber0.05Delay between each character animation (seconds)
durationnumber0.6Duration of each character animation (seconds)
classNamestring""Additional CSS classes

Usage Examples

Scale Characters
Blur Effect
Slide Animation
Rotate Text
Fade In
Fast Scale