← All Guides
tutorialsreactanimationtext-effects

5 Text Animation Techniques in React

Learn how to create stunning text animations in React using Framer Motion, CSS, and Canvas — from typewriter effects to glitch distortion.

Froiden·Apr 10, 2026·8 min

Text animations are the fastest way to make a landing page feel alive. A well-placed typewriter effect or a glitch-on-hover treatment can be the difference between a page that feels flat and one that makes someone stop scrolling.

Here are five techniques we use at Froiden UI, ranked from simplest to most advanced.

1. Typewriter Effect

The classic. Characters appear one by one with a blinking cursor, then optionally delete and retype a new word.

How it works: A setInterval reveals characters from a word array. When the word is complete, it pauses, then deletes character by character before moving to the next word.

const [displayText, setDisplayText] = useState("");
const [wordIndex, setWordIndex] = useState(0);
const [charIndex, setCharIndex] = useState(0);
const [isDeleting, setIsDeleting] = useState(false);

The key to making it feel realistic: variable typing speed. Nobody types at a constant rate. Add Math.random() * 50 to your interval.

Try it: Typewriter Text component

2. Scramble Text on Hover

When the user hovers, characters cycle through random glyphs before resolving to the real text. Think movie hacking terminals or cyberpunk interfaces.

How it works: On mouseenter, each character position starts cycling through a scrambleChars set ("!@#$%^&*") at a fast interval. Characters resolve one by one from left to right, with a stagger delay.

const scrambleChars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789!@#$%^&*";
 
// For each position, pick a random character
const randomChar = scrambleChars[Math.floor(Math.random() * scrambleChars.length)];

The progressive reveal — where resolved characters "catch up" from left to right — is what makes it feel intentional rather than random.

Try it: Scramble Text component

3. Text Highlight on Scroll

Words progressively fill with color as you scroll, like a karaoke prompt. This is scroll-driven — no JavaScript animation loop needed.

How it works: Use Framer Motion's useScroll to get the scroll progress within a target element. Each word maps a slice of that progress to its opacity/color:

const { scrollYProgress } = useScroll({ target: ref });
 
// Word at index 3 of 10 words:
// starts highlighting at 30% scroll, fully highlighted at 40%
const wordOpacity = useTransform(
  scrollYProgress,
  [start, end],
  [baseColor, highlightColor]
);

This technique works best for pull quotes, mission statements, or any text you want people to actually read.

Try it: Text Highlight on Scroll component

4. Split-Flap Display

The airport departure board aesthetic. Each character position has a physical "flap" that rotates through characters with a 3D hinge animation.

How it works: When the target text changes, each character position cycles through the full character set (A-Z, 0-9) with rotateX animation until it lands on the correct character. Positions have staggered start times for the cascading effect.

<AnimatePresence mode="wait">
  <motion.span
    key={currentChar}
    initial={{ rotateX: -90 }}
    animate={{ rotateX: 0 }}
    exit={{ rotateX: 90 }}
    transition={{ duration: 0.08 }}
  >
    {currentChar}
  </motion.span>
</AnimatePresence>

The stagger timing is critical — too fast and it looks like a simple replace; too slow and it feels broken.

Try it: Split-Flap Display component

5. Glitch Text

RGB channel splitting with canvas-rendered scanlines and noise. The most visually complex technique, but also the most viral.

How it works: Three layers of the same text are stacked:

  1. Red channel — offset left/up with a clip-path slice
  2. Cyan channel — offset right/down with a different clip-path slice
  3. Main text — subtle position jitter

A canvas overlay adds scanlines (alternating 1px transparent/opaque rows) and random noise pixels.

// Red channel offset
<span style={{
  color: "rgba(255, 0, 0, 0.7)",
  transform: `translate(${offset}px, ${-offset/2}px)`,
  clipPath: `polygon(0 15%, 100% 15%, 100% 50%, 0 50%)`,
}} />

Trigger on hover for interactive feel, or set autoGlitch for ambient animation.

Try it: Glitch Text component

Which One Should You Use?

TechniqueBest ForComplexity
TypewriterHero headlines, CTAsLow
ScrambleNavigation, labelsLow
Scroll HighlightLong-form content, quotesMedium
Split-FlapStatus displays, countersMedium
GlitchCreative/gaming sitesHigh

All five are available as free, copy-paste components on Froiden UI. Browse the full text effects collection.