Slide Up Reveal Text Animation
Lorem ipsum, dolor sit amet consectetur adipisicing elit. Eligendi labore iusto sit ex tenetur inventore.
Lorem ipsum dolor sit amet consectetur adipisicing elit. Dolor ea laborum, accusamus blanditiis incidunt provident ipsum amet eligendi facere perferendis eos dicta quis, natus omnis repellat ratione doloremque vitae perspiciatis ipsam debitis obcaecati. Ullam incidunt natus accusamus cum eos iure! Beatae quasi rem ad repudiandae voluptatum ut. Corporis, neque earum.
Lorem ipsum dolor sit, amet consectetur adipisicing elit. Autem veniam ducimus rem fuga. Explicabo maiores aspernatur aut reprehenderit harum esse quasi? Magnam fugit natus nesciunt commodi ut ullam rem amet.
- Next.js
- Typescript
- GSAP
- ScrollTrigger Plugin
- SplitText Plugin
- useGSAP Plugin
- Tailwind CSS
components/animated-text.tsx
"use client";
import React, { useRef } from "react";
import gsap from "gsap";
import { SplitText } from "gsap/SplitText";
import { ScrollTrigger } from "gsap/ScrollTrigger";
import { useGSAP } from "@gsap/react";
gsap.registerPlugin(SplitText, ScrollTrigger);
interface AnimatedTextProps {
children: React.ReactNode;
animateOnScroll?: boolean;
delay?: number;
className?: string;
}
export function AnimatedText({
children,
animateOnScroll = true,
delay = 0,
className,
}: AnimatedTextProps) {
const containerRef = useRef<HTMLDivElement>(null);
const splitRefs = useRef<SplitText[]>([]);
useGSAP(
() => {
if (!containerRef.current) return;
async function initializeAnimation() {
await document.fonts.ready;
const container = containerRef.current!;
const elements = Array.from(container.children)
const allLines: HTMLElement[] = [];
splitRefs.current = [];
for (const element of elements) {
if (!(element instanceof HTMLElement)) continue;
const split = SplitText.create(element, {
type: "lines",
mask: "lines",
linesClass: "line++",
lineThreshold: 0.1,
});
splitRefs.current.push(split);
split.lines.forEach((line) => {
line.classList.add(
"relative",
"will-change-transform",
"pb-[0.2em]",
"-mb-[0.2em]",
);
});
allLines.push(...(split.lines as HTMLElement[]));
}
if (allLines.length === 0) return;
gsap.set(allLines, { y: "100%" });
const animationConfig = {
y: "0%",
duration: 1,
stagger: 0.1,
ease: "power4.out" as const,
delay,
...(animateOnScroll && {
scrollTrigger: {
trigger: container,
start: "top 90%",
once: true,
},
}),
};
gsap.to(allLines, animationConfig);
}
initializeAnimation();
return () => {
splitRefs.current.forEach((split) => split?.revert());
};
},
{ scope: containerRef, dependencies: [animateOnScroll, delay] },
);
return (
<div ref={containerRef} className={className}>
{children}
</div>
);
}
<AnimatedText delay={0.2}>
<p className="text-3xl">
Lorem ipsum, dolor sit amet consectetur adipisicing elit. Eligendi
labore iusto sit ex tenetur inventore.
</p>
</AnimatedText>
<AnimatedText delay={0.5}>
<p>
Lorem ipsum dolor sit amet consectetur adipisicing elit. Dolor ea
laborum, accusamus blanditiis incidunt provident ipsum amet eligendi
facere perferendis eos dicta quis, natus omnis repellat ratione
doloremque vitae perspiciatis ipsam debitis obcaecati. Ullam
incidunt natus accusamus cum eos iure! Beatae quasi rem ad
repudiandae voluptatum ut. Corporis, neque earum.
</p>
<p>
Lorem ipsum dolor sit, amet consectetur adipisicing elit. Autem
veniam ducimus rem fuga. Explicabo maiores aspernatur aut
reprehenderit harum esse quasi? Magnam fugit natus nesciunt commodi
ut ullam rem amet.
</p>
</AnimatedText>