| name | gsap-text |
| description | Use when implementing text animations, text effects, character/word/line animations, text reveals, scrambling effects, or using SplitText, TextPlugin, ScrambleTextPlugin. |
GSAP Text Animations
GSAP provides powerful tools for text animation through SplitText, TextPlugin, and ScrambleTextPlugin. Create dramatic reveals, highlights, and interactive text effects.
Installation
SplitText (formerly members-only; now included)
npm install gsap
import { SplitText } from 'gsap/SplitText'
gsap.registerPlugin(SplitText)
TextPlugin (Free)
import { TextPlugin } from 'gsap/TextPlugin'
gsap.registerPlugin(TextPlugin)
ScrambleTextPlugin (formerly members-only; now included)
import { ScrambleTextPlugin } from 'gsap/ScrambleTextPlugin'
gsap.registerPlugin(ScrambleTextPlugin)
SplitText
Basic Setup
gsap.registerPlugin(SplitText)
const split = new SplitText('#myText', {
type: 'chars,words,lines'
})
console.log(split.chars)
console.log(split.words)
console.log(split.lines)
Split Types
const split = new SplitText('#myText', {
type: 'chars'
})
const split = new SplitText('#myText', {
type: 'words'
})
const split = new SplitText('#myText', {
type: 'lines'
})
const split = new SplitText('#myText', {
type: 'chars,words,lines'
})
const split = new SplitText('#myText', {
type: 'chars,words,lines'
})
Character Animations
const split = new SplitText('#heading', { type: 'chars' })
gsap.from(split.chars, {
opacity: 0,
y: 20,
stagger: 0.05,
duration: 0.5,
ease: 'back.out(1.7)'
})
gsap.from(split.chars, {
opacity: 0,
scale: 0,
rotation: () => gsap.utils.random(-20, 20),
stagger: 0.03,
duration: 0.8,
ease: 'elastic.out(1, 0.5)'
})
Word Animations
const split = new SplitText('#paragraph', { type: 'words' })
gsap.from(split.words, {
opacity: 0,
x: -30,
stagger: 0.1,
duration: 0.6,
ease: 'power2.out'
})
gsap.from(split.words, {
opacity: 0,
y: 50,
stagger: {
each: 0.15,
from: 'center',
ease: 'back.out(1.7)'
},
duration: 0.8
})
Line Animations
const split = new SplitText('#paragraph', { type: 'lines' })
gsap.from(split.lines, {
opacity: 0,
y: 50,
stagger: 0.2,
duration: 0.8,
ease: 'power2.out'
})
gsap.from(split.lines, {
opacity: 0,
x: (i) => i % 2 === 0 ? -100 : 100,
stagger: 0.15,
duration: 0.7,
ease: 'power2.out'
})
Combined Split Animations
const split = new SplitText('#text', { type: 'chars,words,lines' })
gsap.from(split.chars, {
opacity: 0,
scale: 0.5,
stagger: 0.02,
duration: 0.5,
ease: 'back.out(1.7)'
})
gsap.from(split.words, {
opacity: 0,
y: 30,
stagger: 0.1,
duration: 0.5,
ease: 'power2.out',
delay: 0.8
})
Stagger Patterns
const split = new SplitText('#text', { type: 'chars' })
gsap.from(split.chars, {
opacity: 0,
scale: 0,
stagger: {
each: 0.02,
from: 'center',
ease: 'power2.out'
},
duration: 0.8
})
gsap.from(split.chars, {
opacity: 0,
y: 20,
stagger: {
each: 0.02,
from: 'edges',
ease: 'power2.out'
},
duration: 0.6
})
gsap.from(split.chars, {
opacity: 0,
scale: 0,
stagger: {
each: 0.02,
from: 'center',
grid: [10, 5],
ease:
},
:
})
Responsive Splits
const split = new SplitText('#text', {
type: 'chars,words',
wordsClass: 'word',
charsClass: 'char'
})
window.addEventListener('resize', () => {
split.revert()
new SplitText('#text', {
type: 'chars,words',
wordsClass: 'word',
charsClass: 'char'
})
})
const mm = gsap.matchMedia()
mm.add('(min-width: 768px)', () => {
const split = new SplitText('#text', { type: 'chars' })
gsap.from(split.chars, { opacity: 0, y: 20, stagger: 0.02 })
return () => split.revert()
})
Cleanup
const split = new SplitText('#text', { type: 'chars' })
split.revert()
split.chars.revert()
SplitText.revert()
ScrambleTextPlugin
Basic Scramble
gsap.registerPlugin(ScrambleTextPlugin)
gsap.to('#text', {
duration: 2,
scrambleText: {
chars: 'upperCase',
revealDelay: 0.5,
speed: 0.3
}
})
Custom Characters
gsap.to('#text', {
duration: 2,
scrambleText: {
chars: '!<>-_\\/[]{}—=+*^?#________',
speed: 0.2
}
})
Text Change
gsap.to('#text', {
duration: 2,
scrambleText: {
text: 'New Text Here',
chars: 'XO',
revealDelay: 0.3,
speed: 0.4
}
})
Reveal Pattern
gsap.to('#text', {
duration: 3,
scrambleText: {
chars: '0123456789',
revealDelay: 1,
speed: 0.1
}
})
Decode Effect
gsap.to('#secret', {
duration: 4,
scrambleText: {
text: 'DECODED MESSAGE',
chars: 'ABCDEFGHIJKLMNOPQRSTUVWXYZ',
revealDelay: 2,
speed: 0.2
}
})
Speed Control
gsap.to('#text', {
duration: 2,
scrambleText: {
chars: 'upperCase',
speed: 0.1,
revealDelay: 1.5
}
})
gsap.to('#text', {
duration: 1,
scrambleText: {
chars: 'upperCase',
speed: 0.8,
revealDelay: 0.2
}
})
Combined with SplitText
const split = new SplitText('#text', { type: 'chars' })
gsap.from(split.chars, {
opacity: 0,
scrambleText: {
chars: 'XO',
speed: 0.3,
revealDelay: 0.5
},
stagger: 0.03,
duration: 2,
ease: 'power2.out'
})
TextPlugin
Basic Text Change
gsap.registerPlugin(TextPlugin)
gsap.to('#text', {
duration: 1,
text: 'New text content'
})
Incremental Text
gsap.to('#counter', {
duration: 2,
text: {
value: 1000,
delimiter: '',
padZeroes: true
}
})
Array Text
const phrases = ['Hello', 'World', 'GSAP', 'Text']
gsap.to('#text', {
duration: 3,
text: {
value: phrases,
delimiter: ' ',
newClass: 'new-text',
oldClass: 'old-text'
}
})
ScrollTrigger + Text
Scroll Reveal
gsap.registerPlugin(ScrollTrigger, SplitText)
const split = new SplitText('#text', { type: 'chars' })
gsap.from(split.chars, {
opacity: 0,
y: 30,
stagger: 0.02,
scrollTrigger: {
trigger: '#text',
start: 'top 80%',
toggleActions: 'play none none reverse'
}
})
Scrolling Highlight
const split = new SplitText('#text', { type: 'chars' })
gsap.to(split.chars, {
color: '#ff0000',
scale: 1.2,
stagger: 0.01,
scrollTrigger: {
trigger: '#text',
start: 'top center',
end: 'bottom center',
scrub: true
}
})
Scroll Scramble
gsap.to('#text', {
duration: 2,
scrambleText: {
text: 'Scrambled Text',
chars: 'XO',
speed: 0.3
},
scrollTrigger: {
trigger: '#text',
start: 'top 80%',
toggleActions: 'play none none reverse'
}
})
Text Effects Patterns
Typewriter Effect
const split = new SplitText('#text', { type: 'chars' })
gsap.from(split.chars, {
opacity: 0,
x: -10,
stagger: 0.05,
duration: 0.1,
ease: 'none'
})
Wave Effect
const split = new SplitText('#text', { type: 'chars' })
gsap.from(split.chars, {
y: -50,
opacity: 0,
stagger: {
each: 0.03,
from: 'center',
ease: 'sine.out'
},
duration: 1
})
Explosion Effect
const split = new SplitText('#text', { type: 'chars' })
gsap.from(split.chars, {
opacity: 0,
scale: 0,
x: () => gsap.utils.random(-200, 200),
y: () => gsap.utils.random(-200, 200),
rotation: () => gsap.utils.random(-180, 180),
stagger: {
each: 0.01,
from: 'random',
ease: 'power2.out'
},
duration: 1.5
})
Glitch Effect
const split = new SplitText('#text', { type: 'chars' })
gsap.to(split.chars, {
x: () => gsap.utils.random(-5, 5),
y: () => gsap.utils.random(-5, 5),
stagger: {
each: 0.02,
from: 'random',
ease: 'steps(3)'
},
duration: 0.3,
repeat: 3,
yoyo: true,
onComplete: () => {
gsap.to(split.chars, { x: 0, y: 0, duration: 0.1 })
}
})
Magnetic Text
const split = new SplitText('#text', { type: 'chars' })
document.querySelectorAll(split.chars).forEach(char => {
gsap.to(char, {
x: 0,
y: 0,
duration: 0.5,
ease: 'elastic.out(1, 0.3)'
})
char.addEventListener('mouseenter', () => {
gsap.to(char, {
x: gsap.utils.random(-10, 10),
y: gsap.utils.random(-10, 10),
duration: 0.2
})
})
})
Performance Tips
Optimize Splits
const split = new SplitText('#long-text', { type: 'chars,words,lines' })
const split = new SplitText('#long-text', { type: 'words' })
Revert When Done
const split = new SplitText('#text', { type: 'chars' })
gsap.from(split.chars, {
opacity: 0,
y: 20,
stagger: 0.02,
duration: 0.5,
onComplete: () => {
split.revert()
}
})
Use matchMedia
const split = new SplitText('#text', { type: 'chars' })
const mm = gsap.matchMedia()
mm.add('(min-width: 768px)', () => {
const split = new SplitText('#text', { type: 'chars' })
gsap.from(split.chars, { opacity: 0, y: 20, stagger: 0.02 })
return () => split.revert()
})
Common Mistakes
1. Forgetting Revert
const split = new SplitText('#text', { type: 'chars' })
const split = new SplitText('#text', { type: 'chars' })
split.revert()
2. Splitting Too Much
const split = new SplitText('#text', { type: 'chars,words,lines' })
const split = new SplitText('#text', { type: 'chars' })
3. Wrong Scramble Speed
gsap.to('#text', {
duration: 5,
scrambleText: {
chars: 'upperCase',
speed: 0.05
}
})
gsap.to('#text', {
duration: 2,
scrambleText: {
chars: 'upperCase',
speed: 0.3
}
})
Best Practices
- Revert splits - Clean up after animations
- Use matchMedia - Responsive text animations
- Choose right split type - Chars, words, or lines based on effect
- Control stagger - Don't make it too slow or too fast
- Combine with ScrollTrigger - Create scroll-based text reveals
- Test performance - Long text with char splits can be heavy
- Use appropriate speed - Scramble should be readable
- Consider accessibility - Ensure text remains accessible
Quick Reference
| Feature | Method |
|---|
| Split chars | new SplitText(target, { type: 'chars' }) |
| Split words | new SplitText(target, { type: 'words' }) |
| Split lines | new SplitText(target, { type: 'lines' }) |
| Revert split | split.revert() |
| Scramble text | gsap.to(target, { scrambleText: { chars, speed } }) |
| Change text | gsap.to(target, { text: 'new text' }) |
| Stagger chars | gsap.from(split.chars, { stagger: 0.02 }) |
| Scroll reveal | gsap.from(split.chars, { scrollTrigger: { ... } }) |