Skip to main content
Anime.js provides powerful text splitting capabilities that allow you to animate text by lines, words, or individual characters.

Text Splitter

The TextSplitter class wraps text content in elements for granular animation control.

Basic Usage

import { text } from 'animejs';

const splitter = new text.TextSplitter('.title', {
  chars: true,
  words: true
});

Split by Characters

import { animate, text } from 'animejs';

const splitter = new text.TextSplitter('.text', {
  chars: true
});

animate(splitter.chars, {
  translateY: [40, 0],
  opacity: [0, 1],
  duration: 800,
  delay: (el, i) => i * 30
});

Split by Words

const splitter = new text.TextSplitter('.paragraph', {
  words: true
});

animate(splitter.words, {
  scale: [0, 1],
  opacity: [0, 1],
  duration: 600,
  delay: (el, i) => i * 50,
  ease: 'out(3)'
});

Split by Lines

const splitter = new text.TextSplitter('.content', {
  lines: true
});

animate(splitter.lines, {
  translateX: [-100, 0],
  opacity: [0, 1],
  duration: 1000,
  delay: (el, i) => i * 100
});

Advanced Options

Custom Templates

Customize the wrapper elements:
const splitter = new text.TextSplitter('.text', {
  chars: {
    class: 'char',
    wrap: 'clip'
  },
  words: {
    class: 'word',
    clone: 'bottom'
  }
});

Template Parameters

class
string
CSS class to apply to wrapper elements
wrap
boolean | 'clip' | string
Wrap elements in additional container. Use ‘clip’ for overflow clipping.
clone
boolean | 'left' | 'right' | 'top' | 'bottom'
Create clone elements for advanced effects. Position determines clone offset direction.

Function Templates

const splitter = new text.TextSplitter('.text', {
  chars: (node) => {
    const char = node.textContent;
    return `<span class="char char-${char}">{value}</span>`;
  }
});
Use {value} as a placeholder for the text content and {i} for the index in custom templates.

Configuration Options

Include Spaces

const splitter = new text.TextSplitter('.text', {
  chars: true,
  includeSpaces: true
});

Accessibility

Keep original text accessible for screen readers:
const splitter = new text.TextSplitter('.text', {
  chars: true,
  accessible: true // Default: true
});
When accessible is true, the original text is preserved in a visually-hidden element for screen readers.

Debug Mode

Visualize split boundaries:
const splitter = new text.TextSplitter('.text', {
  lines: true,
  words: true,
  chars: true,
  debug: true
});

Responsive Behavior

The splitter automatically re-splits text on resize:
const splitter = new text.TextSplitter('.text', {
  lines: true,
  words: true
});

// Text will re-split when window resizes
// Line breaks are recalculated automatically

Manual Refresh

// Force a refresh
splitter.refresh();

Effects with addEffect

Add effects that automatically refresh on resize:
import { animate, text } from 'animejs';

const splitter = new text.TextSplitter('.text', {
  chars: true
});

splitter.addEffect((splitter) => {
  return animate(splitter.chars, {
    translateY: [20, 0],
    opacity: [0, 1],
    duration: 600,
    delay: (el, i) => i * 20
  });
});
Effects added with addEffect() are automatically cleaned up and re-run when the splitter refreshes.

Combining Split Types

const splitter = new text.TextSplitter('.text', {
  lines: true,
  words: true,
  chars: true
});

// Animate lines first
animate(splitter.lines, {
  translateY: [100, 0],
  opacity: [0, 1],
  duration: 800,
  delay: (el, i) => i * 100
});

// Then animate characters within words
animate(splitter.chars, {
  scale: [0, 1],
  duration: 400,
  delay: (el, i) => i * 10 + 800
});

Revert Changes

Restore original HTML:
// Clean up and restore original text
splitter.revert();
Calling revert() removes all split elements and restores the original HTML. Any running animations on split elements will be cancelled.

Stagger Patterns

import { stagger, animate, text } from 'animejs';

const splitter = new text.TextSplitter('.text', {
  chars: true
});

// Stagger from center
animate(splitter.chars, {
  scale: [0, 1],
  opacity: [0, 1],
  duration: 600,
  delay: stagger(50, { from: 'center' })
});

// Stagger in a grid pattern
animate(splitter.chars, {
  translateY: [40, 0],
  opacity: [0, 1],
  duration: 800,
  delay: stagger(30, { grid: [10, 5], from: 'last' })
});

Helper Function

Convenience function for creating text splitters:
import { splitText } from 'animejs';

const splitter = splitText('.text', {
  words: true,
  chars: true
});

Performance Tips

Only split by what you need. Splitting by all three (lines, words, chars) creates many DOM elements:
// Only split by chars if that's all you need
const splitter = new text.TextSplitter('.text', {
  chars: true
});
The built-in resize observer already debounces with a 150ms delay, but you can disable automatic refreshing:
const splitter = new text.TextSplitter('.text', { chars: true });
// Manual control over when to refresh
Call revert() when animations are complete to reduce DOM size:
splitter.addEffect((split) => {
  return animate(split.chars, {
    opacity: [0, 1],
    duration: 1000,
    onComplete: () => splitter.revert()
  });
});

Build docs developers (and LLMs) love