Instruction

Follow instructions to design and launch your site

Icon

Lenis Smooth Scrolling

<link rel="stylesheet" href="https://unpkg.com/lenis@1.3.20/dist/lenis.css" />
<script src="https://unpkg.com/lenis@1.3.20/dist/lenis.min.js"></script>
<script>
gsap.registerPlugin(ScrollTrigger);

const lenis = new Lenis({
duration: 1.5,
easing: (t) => 1 - Math.pow(1 - t, 3),
smooth: true,
smoothTouch: false, // ✅ important
});

// sync
lenis.on('scroll', ScrollTrigger.update);

// raf loop
function raf(time) {
lenis.raf(time);
requestAnimationFrame(raf);
}
requestAnimationFrame(raf);

// ✅ correct scroller
ScrollTrigger.scrollerProxy(document.documentElement, {
scrollTop(value) {
return arguments.length ? lenis.scrollTo(value, { immediate: true }) : lenis.scroll;
},
getBoundingClientRect() {
return {
top: 0,
left: 0,
width: window.innerWidth,
height: window.innerHeight,
};
},
});

// ✅ important
ScrollTrigger.defaults({
scroller: document.documentElement,
});

// refresh fix
ScrollTrigger.addEventListener('refresh', () => lenis.resize());

ScrollTrigger.refresh();
</script>

Counter Gsap

<script>
document.addEventListener("DOMContentLoaded", () => {

  gsap.registerPlugin(ScrollTrigger);

  const counters = document.querySelectorAll(".counter");

  counters.forEach(counter => {

    const text = counter.textContent.trim();

    const number = parseFloat(text.replace(/[^0-9.]/g, ""));
    const suffix = text.replace(/[0-9.,]/g, "").trim();

    const obj = { value: 0 };

    gsap.to(obj, {
      value: number,
      duration: 3,
      ease: "power2.out",

      scrollTrigger: {
        trigger: counter,
        start: "top 85%",
        toggleActions: "play none none none",
        once: true
      },

      onUpdate: () => {

        const finalValue =
          number % 1 !== 0
            ? obj.value.toFixed(1)
            : Math.floor(obj.value);

        counter.textContent =
          Number(finalValue).toLocaleString() + suffix;
      }
    });

  });

});
</script>