Scroll Tags Code
Interactive scroll-triggered tags that fly into a grid board container from all offscreen directions.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188
"use client";
import { useGSAP } from "@gsap/react";
import gsap from "gsap";
import { ScrollTrigger } from "gsap/ScrollTrigger";
import { useRef } from "react";
gsap.registerPlugin(useGSAP, ScrollTrigger);
const tagsData = [
{
text: "CREATIVE",
color: "bg-wtf-orange text-white",
xStart: -400,
yStart: -200,
rotate: -15,
},
{
text: "DEVELOPER",
color: "bg-wtf-green text-white",
xStart: 400,
yStart: 250,
rotate: 12,
},
{
text: "GSAP 3",
color: "bg-wtf-yellow text-black",
xStart: -300,
yStart: 300,
rotate: -8,
},
{
text: "NEXT.JS 16",
color: "bg-wtf-purple text-white",
xStart: 500,
yStart: -150,
rotate: 15,
},
{
text: "REACT 19",
color: "bg-wtf-blue text-white",
xStart: -500,
yStart: 100,
rotate: 5,
},
{
text: "BRUTALIST",
color: "bg-wtf-red text-white",
xStart: 300,
yStart: -300,
rotate: -12,
},
{
text: "SCROLL TRIGGER",
color: "bg-black text-white",
xStart: -600,
yStart: -100,
rotate: 20,
},
{
text: "FLUID MOTION",
color: "bg-white text-black",
xStart: 600,
yStart: 400,
rotate: -6,
},
];
export default function AnimationTwoPage() {
const containerRef = useRef<HTMLDivElement>(null);
const scrollSectionRef = useRef<HTMLDivElement>(null);
useGSAP(
() => {
const tags = gsap.utils.toArray<HTMLElement>(".assembler-tag");
const scroller = containerRef.current?.closest("#main-scroller") || undefined;
// Pin the scroll section and animate the tags entering the DOM
const tl = gsap.timeline({
scrollTrigger: {
trigger: scrollSectionRef.current,
scroller: scroller,
start: "top top",
end: "+=2000",
pin: true,
scrub: 1,
anticipatePin: 1,
},
});
tags.forEach((tag, idx) => {
const xStart = Number(tag.getAttribute("data-xs") || 0);
const yStart = Number(tag.getAttribute("data-ys") || 0);
const rotate = Number(tag.getAttribute("data-rot") || 0);
// Animate each tag flying into its DOM grid cell from offscreen
tl.fromTo(
tag,
{
x: xStart,
y: yStart,
rotation: rotate * 3,
opacity: 0,
scale: 0.2,
},
{
x: 0,
y: 0,
rotation: rotate,
opacity: 1,
scale: 1,
ease: "power2.out",
},
idx * 0.15, // stagger offset in timeline
);
});
},
{ scope: containerRef },
);
return (
<div
className="relative bg-[#f0eadf] text-[#2a2a2a] selection:bg-wtf-yellow selection:text-black"
ref={containerRef}
>
<div className="absolute inset-0 dot-grid pointer-events-none z-0" />
{/* Floating Back Button */}
<div className="fixed left-6 top-6 z-50 pointer-events-auto">
<button
onClick={() =>
window.history.length > 1
? window.history.back()
: (window.location.href = "/")
}
className="brutalist-btn bg-wtf-yellow text-xs font-mono font-bold py-2.5 px-4 rounded-md uppercase cursor-pointer"
>
ā Back
</button>
</div>
{/* Intro section */}
<section className="h-[70vh] flex flex-col items-center justify-center text-center px-4 gap-4 z-10 relative">
<div className="inline-flex items-center gap-2 bg-wtf-green border-2 border-[#2a2a2a] px-4 py-1.5 rounded-full text-[10px] font-mono font-bold text-white uppercase tracking-widest shadow-[3px_3px_0px_#2a2a2a] tilt-right">
<span>Scroll Tags Assembly Sandbox</span>
</div>
<h1 className="text-4xl md:text-6xl font-serif font-black uppercase max-w-2xl leading-[1.1]">
Scroll Down to Assemble the Tags
</h1>
<p className="font-mono text-xs text-zinc-500 uppercase tracking-widest animate-bounce mt-4">
ā Scroll Down ā
</p>
</section>
{/* Assembly ScrollTrigger Section */}
<section
ref={scrollSectionRef}
className="h-[calc(100vh-64px)] w-full flex items-center justify-center relative overflow-hidden bg-white border-y-3 border-[#2a2a2a]"
>
<div className="absolute inset-0 dot-grid opacity-5 pointer-events-none" />
<div className="z-10 w-full max-w-4xl px-4 flex flex-col gap-8 items-center">
<div className="font-mono text-xs font-bold text-zinc-400 uppercase tracking-widest">
DOM Board Collider
</div>
{/* Target grid container where tags land */}
<div className="w-full min-h-[300px] border-3 border-[#2a2a2a] rounded-xl bg-zinc-50 p-8 flex flex-wrap gap-4 items-center justify-center shadow-[inset_4px_4px_10px_rgba(0,0,0,0.05)] relative">
{tagsData.map((tag, i) => (
<span
key={i}
className={`assembler-tag px-6 py-3 border-2 border-[#2a2a2a] rounded-lg font-mono font-black text-sm md:text-base shadow-[3px_3px_0px_#2a2a2a] transform will-change-transform ${tag.color}`}
data-xs={tag.xStart}
data-ys={tag.yStart}
data-rot={tag.rotate}
>
{tag.text}
</span>
))}
</div>
</div>
</section>
</div>
);
}
āļø Setup & Integration Guide
How to install, import, and configure this animation in your project
Option A: Install via CLI (Recommended)
You can install this component directly into your project via the TweenLabs CLI. It automatically creates the file and configures dependencies:
Option B: Manual Installation
Follow these steps to integrate the component into your project manually:
Install Packages
First, install GSAP and its official React hook helper library (@gsap/react).
Add Required CSS Styles
Copy the styles from the Required CSS tab above, or open the styles.css file that was automatically downloaded with your component. Paste these classes into your global stylesheet (e.g. src/app/globals.css or similar).
Create Component File
Create a new file in your React or Next.js project (e.g. src/components/ScrollTags.tsx) and paste the code from the Standalone React Component tab above. If no standalone tab is available, copy the full page file code and adjust the routing logic for your needs.
ā ļø ScrollTrigger Plugin Notice
This component uses scroll-triggered timing events. Make sure to register the plugin as shown inside the code:
import { ScrollTrigger } from "gsap/ScrollTrigger";
gsap.registerPlugin(useGSAP, ScrollTrigger);Import & Render
Import and render the component in your page or view layout:
import ScrollTags from "@/components/ScrollTags";
export default function Page() {
return (
<main className="min-h-screen p-8 bg-[#f5f5f5] flex items-center justify-center">
<ScrollTags />
</main>
);
}Customization & Component Properties
š ļø Customization & Component Properties (Props)
You can pass the following settings to configure the layout and animation details:
tags(Array): An array of tag objects. Each object containstext(string),color(Tailwind class),xStart(number),yStart(number), androtate(number).