Capability 04 — Split text
Four ways to make type arrive.
GSAP SplitText gives us characters, words, and lines as animatable units. Below: four canonical reveals used across Bond’s experience work, each with the code it takes to ship.
Craft is a posture, not a finish.
const split = new SplitText(el, { type: "chars" });
gsap.set(split.chars, {
opacity: 0, y: 24, filter: "blur(10px)",
});
gsap.to(split.chars, {
opacity: 1, y: 0, filter: "blur(0px)",
duration: 0.9, ease: "power3.out",
stagger: 0.025,
});Write fewer words. Choose them slowly.
const split = new SplitText(el, { type: "words" });
gsap.set(split.words, {
opacity: 0, yPercent: 110,
});
gsap.to(split.words, {
opacity: 1, yPercent: 0,
duration: 0.85, ease: "expo.out",
stagger: 0.06,
});The best motion never announces itself. You notice the room became warmer, the type settled into place, and somehow the page you landed on felt like it had been there the whole time, waiting.
const split = new SplitText(el, { type: "lines" });
gsap.set(split.lines, {
clipPath: "inset(0 100% 0 0)",
});
gsap.to(split.lines, {
clipPath: "inset(0 0% 0 0)",
duration: 1.1, ease: "power4.out",
stagger: 0.18,
});Type that arrives with intent.
const glyphs = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789/";
function tick(now) {
const p = Math.min(1, (now - start) / 1400);
const locked = Math.floor(p * target.length);
const out = target.split("").map((ch, i) =>
i < locked ? ch : glyphs[rand(glyphs.length)]
).join("");
setDisplay(out);
if (p < 1) requestAnimationFrame(tick);
}How this is built
One library. Four dialects.
SplitText does the dirty work — segmenting a string into animatable DOM nodes without breaking layout. From there it’s restraint: choose the right unit, choose the right ease, keep the stagger short, and always give reduced-motion users the finished string on first paint.
01GSAP SplitTextOne library, four primitives — chars, words, lines, and combinations thereof. Non-destructive: split.revert() restores the original DOM.View source
02IntersectionObserver triggerEach variant uses a shared useInView hook with a -10% bottom margin. Animations fire on 30–35% visibility, never on load, never twice.View source
03Char stagger, blur-to-focusgsap.set + gsap.to on split.chars with a 25ms stagger and a filter: blur(10px) → blur(0px) transition. Editorial, not gimmicky.View source
04Word stagger, slide-upsplit.words with yPercent: 110 → 0 under an expo.out ease. The line-box clipping creates a letterpress feel without any extra markup.View source
05Line mask via clip-pathsplit.lines with clipPath: inset(0 100% 0 0) → inset(0 0% 0 0). Left-to-right wipe, 180ms stagger, 1.1s power4.out ease.View source
06Character scramblerequestAnimationFrame-driven. Each frame resolves floor(progress × length) characters and replaces the rest with random glyphs from an alphabet.View source
07Reduced-motion fallbackWhen prefers-reduced-motion: reduce is set, every variant skips the split and renders the final string verbatim. Readable on the first paint.View source
08Accessibility: aria-labelThe scramble variant carries an aria-label with the final string so assistive tech reads intent, not noise. SplitText output is visual only.View source