or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

advanced-plugins.mdanimation-control.mdcore-animation.mdcss-properties.mddraggable.mdindex.mdscroll-trigger.mdsvg-animation.mdtext-animation.mdtimeline-system.mdutility-functions.md
tile.json

text-animation.mddocs/

Text Animation

GSAP provides specialized plugins for text animation, including character-by-character effects, typewriter animations, and scrambling effects. These plugins enable sophisticated typography animations.

Setup

import { TextPlugin, SplitText, ScrambleTextPlugin } from "gsap/all";
gsap.registerPlugin(TextPlugin, SplitText, ScrambleTextPlugin);

Capabilities

TextPlugin

Create typewriter and text replacement effects with customizable timing.

interface TextVars {
  text?: string;          // Target text content
  delimiter?: string;     // Character delimiter for typing effect
  speed?: number;         // Typing speed override
  diff?: boolean;         // Only animate differences between old and new text
  padSpace?: boolean;     // Add spaces to maintain layout during typing
}

Usage Examples:

// Basic typewriter effect
gsap.to(".typewriter", {
  duration: 3,
  text: "Hello, World!",
  ease: "none"
});

// Custom delimiter for word-by-word typing
gsap.to(".word-by-word", {
  duration: 2,
  text: "One word at a time",
  delimiter: " "          // Type word by word instead of character by character
});

// Morphing text (only changes animate)
gsap.to(".morphing-text", {
  duration: 1.5,
  text: "New text content",
  diff: true             // Only animate the differences
});

// Preserve layout while typing
gsap.to(".layout-text", {
  duration: 2,
  text: "This maintains spacing",
  padSpace: true
});

SplitText

Split text into individual characters, words, or lines for granular animation control.

/**
 * SplitText constructor for splitting text elements
 * @param targets - Text elements to split
 * @param vars - Split configuration
 */
class SplitText {
  constructor(targets: string | Element | Element[], vars?: SplitText.Vars);
  
  // Properties
  chars: Element[];       // Array of character elements
  words: Element[];       // Array of word elements  
  lines: Element[];       // Array of line elements
  original: Element[];    // Original elements
  
  // Methods
  split(vars?: SplitText.Vars): SplitText;  // Re-split with new options
  revert(): SplitText;                       // Restore original text
}

interface SplitText.Vars {
  type?: "lines" | "words" | "chars" | "lines,words" | "lines,words,chars";
  linesClass?: string;    // CSS class for line elements
  wordsClass?: string;    // CSS class for word elements
  charsClass?: string;    // CSS class for character elements
  tag?: string;           // HTML tag for split elements (default: "div")
  reduceWhiteSpace?: boolean; // Reduce whitespace between elements
}

Usage Examples:

// Split into characters
const splitText = new SplitText(".text", { type: "chars" });

// Animate each character
gsap.from(splitText.chars, {
  duration: 1,
  y: 50,
  opacity: 0,
  stagger: 0.05,
  ease: "back.out(1.7)"
});

// Split into words and lines
const splitWords = new SplitText(".paragraph", { 
  type: "lines,words",
  linesClass: "line",
  wordsClass: "word"
});

// Animate lines sliding in
gsap.from(splitWords.lines, {
  duration: 1,
  x: -100,
  opacity: 0,
  stagger: 0.2
});

// Character reveal animation
const chars = new SplitText(".reveal-text", { type: "chars" });
gsap.set(chars.chars, { opacity: 0, rotationX: -90 });
gsap.to(chars.chars, {
  duration: 0.8,
  opacity: 1,
  rotationX: 0,
  stagger: 0.02,
  ease: "back.out(1.7)"
});

ScrambleTextPlugin

Create scrambling and decoding text effects with customizable character sets.

interface ScrambleTextVars {
  scrambleText?: {
    text?: string;          // Target text
    chars?: string;         // Character set for scrambling
    revealDelay?: number;   // Delay before revealing each character
    speed?: number;         // Scrambling speed
    delimiter?: string;     // Character delimiter
    rightToLeft?: boolean;  // Reveal from right to left
    tweenLength?: boolean;  // Animate text length changes
  };
}

Usage Examples:

// Basic scramble effect
gsap.to(".scramble", {
  duration: 2,
  scrambleText: {
    text: "DECODED MESSAGE",
    chars: "XO",           // Use only X and O for scrambling
    revealDelay: 0.5
  }
});

// Matrix-style effect
gsap.to(".matrix-text", {
  duration: 3,
  scrambleText: {
    text: "THE MATRIX HAS YOU",
    chars: "01",           // Binary characters
    revealDelay: 0.6,
    speed: 0.3
  }
});

// Custom character set
gsap.to(".custom-scramble", {
  duration: 2.5,
  scrambleText: {
    text: "CUSTOM DECODE",
    chars: "!@#$%^&*()+=",
    revealDelay: 0.3,
    rightToLeft: true      // Reveal from right to left
  }
});

Advanced Text Animations

Combining text plugins with other GSAP features for complex effects.

// Typing with cursor effect
const typewriter = gsap.timeline();
gsap.set(".cursor", { opacity: 1 });

typewriter
  .to(".typewriter-text", {
    duration: 2,
    text: "Hello, World!",
    ease: "none"
  })
  .to(".cursor", {
    opacity: 0,
    duration: 0.5,
    repeat: -1,
    yoyo: true
  }, 0);

// Word cloud animation
const words = new SplitText(".word-cloud", { type: "words" });
gsap.set(words.words, { 
  position: "absolute",
  color: () => gsap.utils.random(["red", "blue", "green", "purple"])
});

gsap.from(words.words, {
  duration: 2,
  scale: 0,
  rotation: () => gsap.utils.random(-360, 360),
  x: () => gsap.utils.random(-200, 200),
  y: () => gsap.utils.random(-100, 100),
  stagger: {
    amount: 1.5,
    from: "random"
  },
  ease: "back.out(2)"
});

// Sequential text reveals
const textElements = gsap.utils.toArray(".reveal-line");
const tl = gsap.timeline();

textElements.forEach((element, index) => {
  const split = new SplitText(element, { type: "chars" });
  
  tl.fromTo(split.chars, 
    { 
      opacity: 0, 
      y: 100,
      rotationX: -90
    },
    {
      duration: 0.6,
      opacity: 1,
      y: 0,
      rotationX: 0,
      stagger: 0.02,
      ease: "back.out(1.7)"
    }, 
    index * 0.8
  );
});

// Text morphing with scramble
const morphScramble = gsap.timeline();
morphScramble
  .to(".morph-text", {
    duration: 1,
    scrambleText: {
      text: "",
      chars: "ABCDEFGHIJKLMNOPQRSTUVWXYZ",
      revealDelay: 0
    }
  })
  .to(".morph-text", {
    duration: 1.5,
    scrambleText: {
      text: "NEW MESSAGE",
      chars: "ABCDEFGHIJKLMNOPQRSTUVWXYZ",
      revealDelay: 0.5
    }
  });

Text Layout Considerations

Best practices for text animation layouts and performance.

// Preserve layout during animations
gsap.set(".text-container", { 
  height: "auto",
  overflow: "hidden"
});

// Fix line height issues with SplitText
const split = new SplitText(".text", { type: "lines" });
gsap.set(split.lines, { 
  overflow: "hidden",
  height: "auto"
});

// Responsive text animations
ScrollTrigger.matchMedia({
  "(min-width: 768px)": function() {
    // Desktop text animation
    const largeText = new SplitText(".responsive-text", { type: "chars" });
    gsap.from(largeText.chars, {
      duration: 1,
      y: 50,
      opacity: 0,
      stagger: 0.02
    });
  },
  
  "(max-width: 767px)": function() {
    // Mobile text animation (simpler)
    gsap.from(".responsive-text", {
      duration: 1,
      y: 30,
      opacity: 0
    });
  }
});

// Clean up SplitText when done
const cleanup = () => {
  split.revert(); // Restore original text structure
};

Performance Optimization

Tips for optimizing text animations performance.

// Use CSS transforms instead of layout properties
gsap.from(splitText.chars, {
  duration: 1,
  y: 50,              // Better than changing top/bottom
  opacity: 0,         // Better than visibility
  force3D: true       // Use hardware acceleration
});

// Batch DOM queries
const chars = gsap.utils.toArray(".char");
gsap.set(chars, { opacity: 0 });  // Set all at once

// Use will-change CSS property for elements that will animate
gsap.set(".animated-text", { willChange: "transform, opacity" });

// Clean up after animations
gsap.to(chars, {
  duration: 1,
  opacity: 1,
  stagger: 0.02,
  onComplete: () => {
    gsap.set(chars, { clearProps: "all" }); // Clear inline styles
  }
});