CategoriesAllHeroNavigationFooterCall-to-ActionsFeature SectionsTestimonialsPricingContactGalleryStatsFAQServicesNewsletterAuthMiscellaneousButtons
All Components3D Cube InteractionBorder Logo GridCountdownFlip ButtonExpandable FAQsFlow ButtonGlow ButtonGrayscale CarouselInertia Zoom ParallaxLogo Cloud GridMobile Drawer NavigationPixel PreloaderProject GalleryRing ButtonShowcase CarouselSlide PreloaderSliding Stairs PreloaderStormtrooper FAQText Gradient OpacityThreads ButtonTilt HeadlineUltra Preloader
Code
app/page.tsx
1"use client";
2
3import gsap from "gsap";
4import { ScrollTrigger } from "gsap/ScrollTrigger";
5import React, { useRef, RefObject, useEffect, MutableRefObject } from "react";
6
7const phrase =
8  "It is a long established fact that a reader will be distracted...";
9
10export default function Home() {
11  const refs: MutableRefObject<HTMLSpanElement[]> = useRef([]);
12  const container: RefObject<HTMLElement> = useRef(null);
13
14  useEffect(() => {
15    gsap.registerPlugin(ScrollTrigger);
16
17    createAnimation();
18  }, []);
19
20  const createAnimation = () => {
21    gsap.to(refs.current, {
22      scrollTrigger: {
23        trigger: container.current,
24
25        scrub: true,
26
27        start: `top`,
28
29        end: `+=${window.innerHeight / 1.5}`,
30      },
31
32      opacity: 1,
33
34      ease: "none",
35
36      stagger: 0.1,
37    });
38  };
39
40  const splitWords = (phrase: string) => {
41    const body: JSX.Element[] = [];
42    phrase.split(" ").forEach((word, i) => {
43      const letters = splitLetters(word);
44      body.push(<p key={word + "_" + i}>{letters}</p>);
45    });
46    return body;
47  };
48
49  const splitLetters = (word: string) => {
50    const letters: JSX.Element[] = [];
51
52    word.split("").forEach((letter, i) => {
53      letters.push(
54        <span
55          key={letter + "_" + i}
56          ref={(el) => {
57            if (el) {
58              refs.current.push(el);
59            }
60          }}
61        >
62          {letter}
63        </span>
64      );
65    });
66
67    return letters;
68  };
69
70  return (
71    <main ref={container} className="main">
72      <div className="body">{splitWords(phrase)}</div>
73    </main>
74  );
75}Installation
Initialized a project and installed the necessary dependencies to use this component.
1. Initialize a new Next.js project:
npx create-next-app@latest my-app2. Install GSAP
npm install gsapAdd Styles
src/globals.css
1@tailwind base;
2@tailwind components;
3@tailwind utilities;
4
5body {
6  background: black;
7}
8
9.main {
10  display: flex;
11  height: 100vh;
12  align-items: flex-end;
13  justify-content: center;
14  margin-bottom: 100vh;
15  color: rgb(211, 211, 211);
16}
17
18.body {
19  width: 90%;
20  display: flex;
21  flex-wrap: wrap;
22}
23
24.body p {
25  font-size: 3.5vw;
26  margin: 0px;
27  margin-right: 1.5vw;
28  font-weight: 700;
29}
30
31.body span {
32  opacity: 0.2;
33}