A. Where to Find It
B. How to Change the Numbers
C. How to Change the Animation Speed
D. How to Change When It Starts Animating
E. Thousand Separator Formatting
F. How to Add a New Counter
G. Where to Put the Script
H. Script for Counter animation.
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.12.5/gsap.min.js" defer></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.12.5/ScrollTrigger.min.js" defer></script>
<script>
document.addEventListener("DOMContentLoaded", () => {
if (typeof gsap === "undefined") return;
gsap.registerPlugin(ScrollTrigger);
const counters = document.querySelectorAll("[data-count]");
counters.forEach((el) => {
const rawValue = el.getAttribute("data-count");
if (!rawValue) return;
const target = parseInt(rawValue.replace(/\./g, ""), 10);
if (isNaN(target)) return;
let obj = { value: 0 };
gsap.to(obj, {
value: target,
duration: 2.5,
ease: "power2.out",
onUpdate: () => {
el.textContent = Math.round(obj.value).toLocaleString("id-ID");
},
scrollTrigger: {
trigger: el,
start: "top 85%",
toggleActions: "play none none none"
}
});
});
});
</script>This template includes an optional hover animation for cards using GSAP. Follow the steps below to enable it.
B. Setup Structure
C. Add GSAP Library
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.12.5/gsap.min.js"></script>D. Add Interaction Script
<script>
window.addEventListener("DOMContentLoaded", () => {
const container = document.querySelector(".card-container");
const cards = gsap.utils.toArray(".card");
// Run only on desktop devices with hover support
const isDesktop = window.matchMedia("(min-width: 1024px) and (hover: hover)").matches;
if (!isDesktop) return;
const originalPositions = cards.map(() => ({
x: (Math.random() - 0.5) * 20,
y: (Math.random() - 0.5) * 20,
rotation: (Math.random() - 0.5) * 10,
scale: 1
}));
cards.forEach((card, i) => {
gsap.set(card, {
...originalPositions[i],
force3D: true
});
});
cards.forEach((card, index) => {
card.addEventListener("mouseenter", () => {
gsap.to(card, {
scale: 1.1,
x: 0,
y: 0,
rotation: 0,
duration: 0.4,
ease: "power3.out",
overwrite: "auto"
});
cards.forEach((otherCard, i) => {
if (i !== index) {
const direction = i < index ? -1 : 1;
gsap.to(otherCard, {
x: direction * container.offsetWidth * 0.15,
rotation: direction * 10,
scale: 0.95,
duration: 0.4,
ease: "power3.out",
overwrite: "auto"
});
}
});
});
card.addEventListener("mouseleave", () => {
cards.forEach((c, i) => {
gsap.to(c, {
x: originalPositions[i].x,
y: originalPositions[i].y,
rotation: originalPositions[i].rotation,
scale: 1,
duration: 0.6,
ease: "power3.out",
overwrite: "auto"
});
});
});
});
});
</script>