Instruction

Webflow Template User Guide

GSAP Guide
Every GSAP code used on this template is here. How to edit them and find them is explain on this page. In every code block on this page, we added additional explanation to help you understand everything.

You can find the code in (Site settings) Footer Code.
Lenis Smooth Scroll
<script src="https://unpkg.com/lenis@1.3.1/dist/lenis.min.js"></script> 

 

<script>

// lenis smooth scroll
  
{
  let lenis;

  const initScroll = () => {
    lenis = new Lenis({});
    lenis.on("scroll", ScrollTrigger.update);
    gsap.ticker.add((time) => lenis.raf(time * 1000));
    gsap.ticker.lagSmoothing(0);
  };

  function initGsapGlobal() {
    
    // Do everything that needs to happen
    //  before triggering all
    // the gsap animations 

    initScroll();

    // match reduced motion media
    // const media = gsap.matchMedia();

    // Send a custom
    //  event to all your
    // gsap animations
    // to start them 

    const sendGsapEvent = () => {
      window.dispatchEvent(
        new CustomEvent("GSAPReady", {
          detail: {
            lenis,
          },
        })
      );
    };

    // Check if fonts are already loaded
    
    if (document.fonts.status === "loaded") {
      sendGsapEvent();
    } else {
      document.fonts.ready.then(() => {
        sendGsapEvent();
      });
    }

    // We need specific handling because the
    // grid/list changes the scroll height of the whole container
    //

    let resizeTimeout;
    const onResize = () => {
      clearTimeout(resizeTimeout);
      resizeTimeout = setTimeout(() => {
        ScrollTrigger.refresh();
      }, 50);
    };

    window.addEventListener("resize", () => onResize());
    const resizeObserver = new ResizeObserver((entries) => onResize());
    resizeObserver.observe(document.body);

    queueMicrotask(() => {
      gsap.to("[data-start='hidden']", {
        autoAlpha: 1,
        duration: 0.1,
        delay: 0.2,
      });
    });
  }

  // this only for dev
  
  const documentReady =
    document.readyState === "complete" || document.readyState === "interactive";

  if (documentReady) {
    initGsapGlobal();
  } else {
    addEventListener("DOMContentLoaded", (event) => initGsapGlobal());
  }
}

</script>
Lenis Smooth Scroll is a lightweight JavaScript library that enables buttery-smooth, hardware-accelerated scrolling for websites. It works by intercepting the browser’s native scroll behavior and applying eased, customizable motion, creating a more fluid and refined browsing experience. Lenis supports vertical and horizontal scroll, inertia effects, and syncs seamlessly with animations from libraries like GSAP or ScrollTrigger.
Hero Section GSAP Animation
GSAP animation of image card sliding to get closer.
<script>
  // Hero Section
  // Hero Image Animation
  gsap.registerPlugin(ScrollTrigger);

  // Create one tween we can control
  const tween = gsap.fromTo(".hero-moving-image-wrap",
    { perspective: "0vw" },
    { perspective: "100vw", duration: 3, ease: "power2.inOut", paused: true }
  );

  // Play forward when hero-moving-image-wrap enters
  ScrollTrigger.create({
    trigger: ".hero-moving-image-wrap",
    start: "top 80%",
    onEnter: () => {
      tween.timeScale(1).play(); // forward at normal speed
    }
  });

  // Reverse when reverse-trigger enters
  ScrollTrigger.create({
    trigger: ".reverse-trigger",
    start: "top 80%",
    onEnter: () => {
      tween.timeScale(-1).play(); // reverse smoothly
      gsap.to(tween, { timeScale: -1.5, duration: 0.01 }); // optional: make reverse 2s by adjusting speed
    },
    onLeaveBack: () => {
      tween.timeScale(1).play(); // play forward again when scrolling up
    }
  });
  // END Hero Image Animation
  
</script>
About Section GSAP Animation
Featuring number counter
<script>
  
// About Section  
  // About Counter
  gsap.registerPlugin(ScrollTrigger);

ScrollTrigger.create({
  trigger: ".about-counter",
  start: "top 100%", // starts when the top of .about-counter is 100% down the viewport
  once: true,       // run only once
  onEnter: () => {
    document.querySelectorAll(".number").forEach(counter => {
      let finalValue = parseInt(counter.textContent, 10); // read existing number
      gsap.fromTo(counter, 
        { innerText: 0 }, 
        {
          innerText: finalValue,
          duration: 2,
          ease: "sine.inOut",
          snap: { innerText: 1 }
        }
      );
    });
  }
});

// END About Counter
  
</script>