Instructions

Find easy to follow instructions

GSAP Guide

All GSAP animations used in this template are collected here. On this page, you’ll find guidance on how to locate and edit them. Each code block comes with extra notes to make it easier to understand.

You can find the code in the Embed Code inside this template.

Step 1 - Library and package GSAP

Before that, prepare the library package from GSAP for some animations. This animation makes the scrolling experience smoother across all devices.

<script src="https://unpkg.com/lenis@1.3.1/dist/lenis.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/gsap@3.14.1/dist/gsap.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/gsap@3.14.1/dist/SplitText.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/gsap@3.14.1/dist/ScrollTrigger.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/gsap@3.14.1/dist/ScrambleTextPlugin.min.js"></script>

Animations for headline, subline, and mouse trail.

<script>
	/* =====================================================
     SMOOTH SCROLLING (Desktop & Tablet Only)
  ===================================================== */
   // 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>
Step 2 - Lenis code
Below are all the required script codes.
<script>
  
     // SCRAMBLE TEXT HERO SECTION
    gsap.registerPlugin(ScrambleTextPlugin);

    window.addEventListener("GSAPReady", () => {

      document.querySelectorAll(".text-tagline-std").forEach(el => {
        const original = el.textContent.trim();
        if (!original) return;
        
        el.textContent = "";

        gsap.to(el, {
          duration: 1.8,
          scrambleText: {
            text: original,
            chars: "ab-de+0gh)1",
            speed: 1,
            rightToLeft: false
          },
          delay: 0.2
        });
      });

    });


  
  
  
  // NUMBER ACHIEVEMENT (SPACER AS TRIGGER)
    gsap.registerPlugin(ScrollTrigger);

    window.addEventListener("GSAPReady", () => {

      const trigger = document.querySelector(".spacer-trigger");
      const counters = document.querySelectorAll(".achievement-number");

      if (!trigger || counters.length === 0) return;

      counters.forEach(counter => {
        const target = parseInt(counter.dataset.number, 10);
        if (isNaN(target)) return;

        const obj = { value: 0 };

        gsap.to(obj, {
          value: target,
          duration: 1.6,
          ease: "power3.out",
          scrollTrigger: {
            trigger: trigger,
            start: "top 65%",
            once: true,
            markers: false 
          },
          onUpdate: () => {
            counter.textContent = Math.round(obj.value);
          }
        });
      });
      ScrollTrigger.refresh();

    });

  
  /* =====================================================
     NAVBAR HOVER ANIMATION
  ===================================================== */
  
document.addEventListener("DOMContentLoaded", () => {

  if (typeof gsap === "undefined") {
    console.error("GSAP Error");
    return;
  }

 function splitChars(el) {
    if (!el) return [];
    const text = el.textContent.trim();
    el.textContent = "";
    const chars = [];
    [...text].forEach(ch => {
      const span = document.createElement("span");
      span.textContent = ch === " " ? "\u00A0" : ch;
      span.style.display = "inline-block";
      el.appendChild(span);
      chars.push(span);
    });
    return chars;
  }


  document.querySelectorAll(".navbar-item").forEach(item => {
    const defaultEl = item.querySelector(".navbar-item-text.default");
    const hiddenEl = item.querySelector(".navbar-item-text.hidden");

    if (!defaultEl || !hiddenEl) return;

    const defaultChars = splitChars(defaultEl);
    const hiddenChars = splitChars(hiddenEl);

    gsap.set(defaultChars, { yPercent: 0, opacity: 1 });
    gsap.set(hiddenChars, { yPercent: 100, opacity: 0 });

    const tl = gsap.timeline({ paused: true, defaults: { duration: 0.4, ease: "power2.out" } });
    tl.to(defaultChars, {
      yPercent: -100,
      opacity: 0,
      stagger: 0.03
    }, 0)
    .to(hiddenChars, {
      yPercent: 0,
      opacity: 1,
      stagger: 0.03
    }, 0.05);

    // hover control
    item.addEventListener("mouseenter", () => tl.play());
    item.addEventListener("mouseleave", () => tl.reverse());
  });
});

</script>
Step 3 - How to edit text About us Section - Part 1

If you want to change or edit the main About Us content, you are required to follow the instructions shown in the image above first.

Web design interface showing a text block labeled 'FRACTAL' surrounded by multiple blurred and abstract images on a black background.
Part 2

Next, you must change the opacity from 100% → 0%, then change the Event setting from auto → none. This method applies specifically to the following two div block classes: “wrapper-heading-about-left” and “wrapper-heading-about-right”. After that, you will be able to see the main About Us content.

Web design interface showing a layered visual layout with blur and motion effect images, and text listing Web Development, 3D Artist, Graphic Design, and UI/UX Designer services.
Step 4 - How to edit text Project section

For the project heading text section, you only need to open several div blocks as shown in the image below.

Web development interface showing a project section with overlapping visuals and text elements on a dark background.
Step 5 - How to edit text Review section - Part 1

For the review section, you can follow what is shown in the image above—especially if you want to edit the review card content. If you notice the div block with the class “trigger-track” containing three additional div blocks, it functions as the trigger for the GSAP entrance animation.

Web development interface showing a project section with overlapping visuals and text elements on a dark background.
Part 2

Below is the div block used to modify the Marquee animation in this section.

Web development interface showing a project section with overlapping visuals and text elements on a dark background.