How to create a text stagger animation with GSAP and Elementor (SplitTextPlugin)
SHARE
Elementor Setup for the GSAP text animation
Add a Heading widget to the container where you want the text to appear.
Add an HTML widget to the same container. The HTML widget must be the last item in the container.
Add the text and simply add the GSAP into the HTML widget code from below.
Note for Elementor users:
In Elementor, the heading widget is not just an H1 or H2 and so on. It is always located in a div, so it is important that you address the H1 within the div.
GSAP SplitText Widget is now free!
In the past, GSAP offered memberships to use the SplitText plugin and many other plugins.
As of May 2025, all GSAP plugins are now free.
This is really great! The SplitText plugin has also been improved, making it even more responsive and accessible.
In the past, many tutorials on YouTube offered workarounds for splitting text, for example with SplitType. This is no longer necessary!
GSAP Code
<script src="https://cdn.jsdelivr.net/npm/gsap@3.13.0/dist/gsap.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/gsap@3.13.0/dist/SplitText.min.js"></script>
<script>
gsap.registerPlugin(SplitText);
let mm = gsap.matchMedia();
document.fonts.ready.then(() => {
gsap.set(".stagger h1", { opacity: 1 });
mm.add({
noMotion: "(prefers-reduced-motion: no-preference)",
reducedMotion: "(prefers-reduced-motion: reduce)"
}, (ctx) => {
const { noMotion, reducedMotion } = ctx.conditions;
if (noMotion) {
SplitText.create(".stagger h1", {
type: "chars,words",
mask: "chars",
onSplit(self) {
return gsap.from(self.chars, {
duration: 1,
yPercent: 100,
opacity: 0,
stagger: 0.01,
ease: "power3.out"
});
}
});
} else if (reducedMotion) {
document.querySelectorAll(".stagger h1").forEach(el => {
el.style.opacity = 1;
});
}
return () => {
// Cleanup falls nötig
};
});
});
</script>
GSAP Code for Text Scroll Animation
<script src="https://cdn.jsdelivr.net/npm/gsap@3.13.0/dist/gsap.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/gsap@3.13.0/dist/SplitText.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/gsap@3.13.0/dist/ScrollTrigger.min.js"></script>
<script>
const prefersReducedMotion = window.matchMedia("(prefers-reduced-motion: reduce)").matches;
document.fonts.ready.then(() => {
gsap.set(".staggerscroll h2", { opacity: 1 });
if (prefersReducedMotion) return;
document.querySelectorAll(".staggerscroll h2").forEach((el) => {
const split = SplitText.create(el, {
type: "chars,words",
linesClass: "chars,words",
autoSplit: true,
mask: "chars"
});
gsap.from(split.chars, {
duration: 1,
yPercent: 100,
opacity: 0,
stagger: 0.01,
ease: "power3.out",
scrollTrigger: {
trigger: el,
start: "top 80%",
toggleActions: "play none none none"
}
});
});
});
</script>