A person sitting on a chair in front of a building.

How to Edit GSAP Animations.

This guide helps non-tech users utilize GSAP for animations like text splitting and sliders, focusing on documentation without altering code logic.

GSAP Plugin Registration

What It does

This sets up GSAP basics.

    // ============================================
    // GSAP PLUGIN REGISTRATION
    // ============================================
    gsap.registerPlugin(ScrollTrigger);
    gsap.config({ nullTargetWarn: false });
Code Block 1

Element Map

  • No direct elements; global setup for ScrollTrigger (scroll-based animations) and config to ignore missing targets.

Home Hero Slider

What It does

This animates a hero slider with slides, thumbnails, arrows, and autoplay.

    // ============================================
    // HOME HERO SLIDER WITH GSAP
    // ============================================
    function initHeroSliderAnimations() {
        document.querySelectorAll(".section_home_hero").forEach(section => {
            const heroSliderWrap = section.querySelector(".home_hero_slider");
            if (!heroSliderWrap) return;

            const heroSliderArrows = section.querySelectorAll(".slider_button");
            const heroSliderItems = heroSliderWrap.querySelectorAll(".home_hero_slider_item");
            const heroThumbnailContainer = section.querySelector(".custom_slider_thumbnail");
            const totalHeroSlides = heroSliderItems.length;
            let heroActiveIndex = 0;
            let heroCurrentTimeline = null;
            let heroAutoplayInterval;

            function startHeroAutoplay() {
                if (heroAutoplayInterval) heroAutoplayInterval.kill();
                heroAutoplayInterval = gsap.delayedCall(7, () => {
                    goNextHero(heroActiveIndex + 1);
                    startHeroAutoplay();
                });
            }

            function buildHeroThumbnails() {
                while (heroThumbnailContainer.firstChild) {
                    heroThumbnailContainer.removeChild(heroThumbnailContainer.firstChild); // Safe clear without innerHTML
                }

                heroSliderItems.forEach((item, index) => {
                    const heroImgElement = item.querySelector(".home_hero_slider_image img");
                    if (!heroImgElement) return;

                    const heroImgSrc = heroImgElement.getAttribute("src");

                    const heroThumbnail = document.createElement("div");
                    heroThumbnail.className = `thumbnail ${index === 0 ? "active" : ""}`;
                    heroThumbnail.dataset.index = index;

                    const img = document.createElement("img");
                    img.className = "object-cover-fit";
                    img.src = heroImgSrc;
                    img.alt = `Thumbnail ${index + 1}`;

                    heroThumbnail.appendChild(img);
                    heroThumbnailContainer.appendChild(heroThumbnail);
                });

                // Animate thumbnails with GSAP
                const heroThumbnails = heroThumbnailContainer.querySelectorAll('.thumbnail');
                gsap.from(heroThumbnails, {
                    scale: 0,
                    duration: 0.5,
                    stagger: 0.1,
                    ease: "back.out(1.7)"
                });
            }


            buildHeroThumbnails();
            const heroThumbnails = section.querySelectorAll(".thumbnail");

            function moveHeroSlide(nextIndex, forwards) {
                if (nextIndex === heroActiveIndex) return;
                if (heroCurrentTimeline) {
                    heroCurrentTimeline.kill();
                    heroCurrentTimeline = null;
                }

                // Animate thumbnails with GSAP
                gsap.to(heroThumbnails, {
                    scale: 1,
                    duration: 0.3,
                    ease: "power1.out"
                });
                heroThumbnails.forEach(thumb => thumb.classList.remove("active"));

                heroThumbnails[nextIndex].classList.add("active");
                gsap.to(heroThumbnails[nextIndex], {
                    scale: 1.1,
                    duration: 0.3,
                    ease: "power1.out"
                });

                const prevHeroItem = heroSliderItems[heroActiveIndex];
                const nextHeroItem = heroSliderItems[nextIndex];
                const oldHeroIndex = heroActiveIndex;
                heroActiveIndex = nextIndex;

                // Set z-index with GSAP
                heroSliderItems.forEach((item, i) => {
                    gsap.set(item, {
                        zIndex: i === nextIndex ? 2 : (i === oldHeroIndex ? 1 : 0)
                    });
                });

                const nextHeroSliderImage = nextHeroItem.querySelector(".home_hero_slider_image img");
                if (nextHeroSliderImage) {
                    gsap.set(nextHeroSliderImage, { scale: 1.15 });
                }

                prevHeroItem.classList.add("is-active");
                nextHeroItem.classList.add("is-active");

                const heroTitleFrom = forwards ? 100 : -100;
                const heroTitleDelay = forwards ? "<50%" : "<";

                heroCurrentTimeline = gsap.timeline({
                    defaults: { duration: 1, ease: "power1.out" },
                    onComplete: () => {
                        prevHeroItem.classList.remove("is-active");
                        heroSliderItems.forEach((item, i) => {
                            gsap.set(item, { zIndex: i === heroActiveIndex ? 2 : 0 });
                        });

                        const activeHeroSliderImage = nextHeroItem.querySelector(".home_hero_slider_image img");
                        if (activeHeroSliderImage) {
                            gsap.to(activeHeroSliderImage, {
                                scale: 1,
                                duration: 4,
                                ease: "power1.out"
                            });
                        }

                        heroCurrentTimeline = null;
                    }
                });

                // Slide transitions with GSAP
                if (forwards) {
                    heroCurrentTimeline.fromTo(
                        nextHeroItem,
                        { clipPath: "polygon(100% 0%, 100% 0%, 100% 100%, 100% 100%)" },
                        { clipPath: "polygon(0% 0%, 100% 0%, 100% 100%, -30% 100%)" }
                    );
                    heroCurrentTimeline.fromTo(
                        prevHeroItem,
                        { clipPath: "polygon(0% 0%, 100% 0%, 100% 100%, 0% 100%)" },
                        { clipPath: "polygon(0% 0%, 0% 0%, -30% 100%, 0% 100%)" },
                        "<"
                    );
                } else {
                    heroCurrentTimeline.fromTo(
                        nextHeroItem,
                        { clipPath: "polygon(0% 0%, 0% 0%, 0% 100%, 0% 100%)" },
                        { clipPath: "polygon(0% 0%, 100% 0%, 130% 100%, 0% 100%)" }
                    );
                    heroCurrentTimeline.fromTo(
                        prevHeroItem,
                        { clipPath: "polygon(0% 0%, 100% 0%, 100% 100%, 0% 100%)" },
                        { clipPath: "polygon(100% 0%, 100% 0%, 100% 100%, 130% 100%)" },
                        "<"
                    );
                }

                // Animate text with GSAP
                const heroTitleElements = nextHeroItem.querySelectorAll(".home_hero_slider_meta");
                heroCurrentTimeline.fromTo(
                    heroTitleElements,
                    { yPercent: heroTitleFrom, autoAlpha: 0 },
                    { yPercent: 0, autoAlpha: 1, duration: 0.5 },
                    heroTitleDelay
                );
            }

            function goNextHero(num) {
                const nextHeroIndex = num >= totalHeroSlides ? 0 : num;
                moveHeroSlide(nextHeroIndex, true);
                startHeroAutoplay();
            }

            function goPrevHero(num) {
                const nextHeroIndex = num < 0 ? totalHeroSlides - 1 : num;
                moveHeroSlide(nextHeroIndex, false);
                startHeroAutoplay();
            }

            // Initialize first slide animation with GSAP
            const firstHeroSliderImage = heroSliderItems[0]?.querySelector(".home_hero_slider_image img");
            if (firstHeroSliderImage) {
                gsap.fromTo(
                    firstHeroSliderImage,
                    { scale: 1.15 },
                    { scale: 1, duration: 4, ease: "power1.out" }
                );
            }

            gsap.set(heroThumbnails[0], { scale: 1.1 });

            startHeroAutoplay();

            // Setup arrow controls with GSAP hover effects
            section.querySelectorAll(".slider_button").forEach(arrow => {
                if (arrow.classList.contains("is-next")) {
                    arrow.addEventListener("click", () => {
                        goNextHero(heroActiveIndex + 1);
                        startHeroAutoplay();
                    });
                }
                if (arrow.classList.contains("is-prev")) {
                    arrow.addEventListener("click", () => {
                        goPrevHero(heroActiveIndex - 1);
                        startHeroAutoplay();
                    });
                }
            });

            // Setup thumbnail controls with GSAP hover effects
            heroThumbnails.forEach((thumb) => {
                thumb.addEventListener("click", () => {
                    const index = parseInt(thumb.dataset.index);
                    moveHeroSlide(index, index > heroActiveIndex);
                    startHeroAutoplay();
                });
            });
        });
    }
Code Block 2

Element Map

  • .section_home_hero: Hero section container.

  • .home_hero_slider_item: Individual slides; scale and fade.

  • .home_hero_slider_image img: Images zoom out slowly.

  • .home_hero_slider_meta: Text slides in on change.

  • .custom_slider_thumbnail: Thumbnails container; thumbnails scale in.

  • .slider_button.is-next, .slider_button.is-prev: Arrows for navigation.

HTML Requirement

A section with class section_home_hero containing a div home_hero_slider with multiple home_hero_slider_item divs (each with image and meta text), a custom_slider_thumbnail div, and arrow buttons.

Customizing Key Variables

  • Autoplay delay: Change gsap.delayedCall(7, ...) to gsap.delayedCall(10, ...) for 10-second wait.

    gsap.delayedCall(10, () => { ... });
  • Slide duration: In timeline, change defaults: { duration: 1, ... } to defaults: { duration: 1.5, ... } for slower transitions.

    heroCurrentTimeline = gsap.timeline({
        defaults: { duration: 1.5, ease: "power1.out" },
        ...
    });
  • Ease: Change "power1.out" to "bounce.out" for bouncy feel.

Removing Animations

  • Comment/Remove entire code shown in the Code Block 2

Testimony Slider

What It does

This animates a testimony slider with images, text, arrows, and autoplay.

    // ============================================
    // TESTIMONY SLIDER WITH GSAP
    // ============================================

    function initTestimonySliderAnimations() {
        const testimonyImageWrap = document.querySelector('.testimony_image-wrap');
        const testimonyImages = testimonyImageWrap?.querySelectorAll('.testimony_image') || [];
        const testimonyTextWrap = document.querySelector('.testimony_text-wrap');
        const testimonyTexts = testimonyTextWrap?.querySelectorAll('.testimony_text') || [];
        const testimonyNextArrow = document.querySelector('.testimony_arrow.is-next');
        const testimonyPrevArrow = document.querySelector('.testimony_arrow.is-prev');

        if (!testimonyImageWrap || !testimonyTextWrap || !testimonyNextArrow || !testimonyPrevArrow ||
            testimonyImages.length === 0 || testimonyTexts.length === 0) {
            return;
        }

        let testimonyActiveIndex = 0;
        let testimonyCurrentTimeline = null;
        let testimonyAutoplayInterval = null;

        function startTestimonyAutoplay() {
            if (testimonyAutoplayInterval) testimonyAutoplayInterval.kill();
            testimonyAutoplayInterval = gsap.delayedCall(7, () => {
                goNextTestimony();
                startTestimonyAutoplay();
            });
        }

        function moveTestimonySlide(nextIndex, direction) {
            if (nextIndex === testimonyActiveIndex) return;

            if (testimonyCurrentTimeline) {
                testimonyCurrentTimeline.kill();
                testimonyCurrentTimeline = null;
            }

            const prevTestimonyImage = testimonyImages[testimonyActiveIndex];
            const nextTestimonyImage = testimonyImages[nextIndex];
            const prevTestimonyText = testimonyTexts[testimonyActiveIndex];
            const nextTestimonyText = testimonyTexts[nextIndex];

            testimonyImages.forEach((img, i) => img.classList.toggle('is-active', i === nextIndex));
            testimonyTexts.forEach((text, i) => text.classList.toggle('is-active', i === nextIndex));

            gsap.set(prevTestimonyImage, { zIndex: 1, autoAlpha: 1 });
            gsap.set(nextTestimonyImage, { zIndex: 2, autoAlpha: 1 });
            gsap.set(prevTestimonyText, { zIndex: 1, autoAlpha: 1 });
            gsap.set(nextTestimonyText, { zIndex: 2, autoAlpha: 1 });

            const oldTestimonyIndex = testimonyActiveIndex;
            testimonyActiveIndex = nextIndex;

            testimonyCurrentTimeline = gsap.timeline({
                defaults: {
                    duration: 1,
                    ease: 'power2.inOut'
                },
                onComplete: () => {
                    if (testimonyActiveIndex !== oldTestimonyIndex) {
                        gsap.set(prevTestimonyImage, { autoAlpha: 0, zIndex: 0 });
                        gsap.set(prevTestimonyText, { autoAlpha: 0, zIndex: 0 });
                    }

                    testimonyImages.forEach((img, i) => {
                        if (i !== testimonyActiveIndex) {
                            gsap.set(img, { zIndex: 0, autoAlpha: 0 });
                        }
                    });
                    testimonyTexts.forEach((text, i) => {
                        if (i !== testimonyActiveIndex) {
                            gsap.set(text, { zIndex: 0, autoAlpha: 0 });
                        }
                    });

                    gsap.set(testimonyImages[testimonyActiveIndex], { zIndex: 2, autoAlpha: 1 });
                    gsap.set(testimonyTexts[testimonyActiveIndex], { zIndex: 2, autoAlpha: 1 });

                    testimonyCurrentTimeline = null;
                }
            });

            if (direction === 'next') {
                testimonyCurrentTimeline.fromTo(
                    nextTestimonyImage,
                    { clipPath: 'polygon(100% 0%, 100% 0%, 100% 100%, 100% 100%)' },
                    { clipPath: 'polygon(0% 0%, 100% 0%, 100% 100%, 0% 100%)' }
                );
                testimonyCurrentTimeline.fromTo(
                    prevTestimonyImage,
                    { clipPath: 'polygon(0% 0%, 100% 0%, 100% 100%, 0% 100%)' },
                    { clipPath: 'polygon(0% 0%, 0% 0%, 0% 100%, 0% 100%)' },
                    '<'
                );
            } else {
                testimonyCurrentTimeline.fromTo(
                    nextTestimonyImage,
                    { clipPath: 'polygon(0% 0%, 0% 0%, 0% 100%, 0% 100%)' },
                    { clipPath: 'polygon(0% 0%, 100% 0%, 100% 100%, 0% 100%)' }
                );
                testimonyCurrentTimeline.fromTo(
                    prevTestimonyImage,
                    { clipPath: 'polygon(0% 0%, 100% 0%, 100% 100%, 0% 100%)' },
                    { clipPath: 'polygon(100% 0%, 100% 0%, 100% 100%, 100% 100%)' },
                    '<'
                );
            }

            testimonyCurrentTimeline.fromTo(
                prevTestimonyText,
                { y: 0, autoAlpha: 1 },
                { y: -50, autoAlpha: 0, duration: 0.5 },
                '<'
            );
            testimonyCurrentTimeline.fromTo(
                nextTestimonyText,
                { y: 50, autoAlpha: 0 },
                { y: 0, autoAlpha: 1, duration: 0.5 },
                '<'
            );
        }

        function goNextTestimony() {
            const nextTestimonyIndex = (testimonyActiveIndex + 1) % testimonyImages.length;
            moveTestimonySlide(nextTestimonyIndex, 'next');
            startTestimonyAutoplay();
        }

        function goPrevTestimony() {
            const prevTestimonyIndex = (testimonyActiveIndex - 1 + testimonyImages.length) % testimonyImages.length;
            moveTestimonySlide(prevTestimonyIndex, 'prev');
            startTestimonyAutoplay();
        }

        // Initialize slider state with GSAP
        testimonyImages.forEach((img, index) => {
            img.classList.toggle('is-active', index === testimonyActiveIndex);
            gsap.set(img, {
                autoAlpha: index === testimonyActiveIndex ? 1 : 0,
                clipPath: 'polygon(0% 0%, 100% 0%, 100% 100%, 0% 100%)',
                zIndex: index === testimonyActiveIndex ? 2 : 0
            });
        });

        testimonyTexts.forEach((text, index) => {
            text.classList.toggle('is-active', index === testimonyActiveIndex);
            gsap.set(text, {
                autoAlpha: index === testimonyActiveIndex ? 1 : 0,
                y: index === testimonyActiveIndex ? 0 : 50,
                zIndex: index === testimonyActiveIndex ? 2 : 0
            });
        });

        // Setup click handlers
        testimonyNextArrow.addEventListener('click', goNextTestimony);
        testimonyPrevArrow.addEventListener('click', goPrevTestimony);

        // Start autoplay with GSAP
        startTestimonyAutoplay();
    }
Code Block 3

Element Map

  • .testimony_image-wrap: Images container; images clip in/out.

  • .testimony_image: Individual images; fade and slide.

  • .testimony_text-wrap: Texts container.

  • .testimony_text: Individual texts; slide up/down.

  • .testimony_arrow.is-next, .testimony_arrow.is-prev: Arrows.

HTML Requirements

Divs testimony_image-wrap with multiple testimony_image, testimony_text-wrap with matching testimony_text, and arrow elements.

Customizing Key Variables

  • Autoplay: 7 → 5.

    testimonyAutoplayInterval = gsap.delayedCall(5, () => { ... });
  • Duration: duration: 1 → 0.8.

    testimonyCurrentTimeline = gsap.timeline({
        defaults: { duration: 0.8, ease: 'power2.inOut' },
        ...
    });
  • Text: duration: 0.5 → 0.7.

    duration: 0.7
  • Ease: "power2.inOut" → "power3.inOut".

Removing Animations

  • Comment/Remove: // function initTestimonySlider() {..}

  • Or Comment/Remove: The code from page settings that are shown in Code Block 3

Expertise Section with GSAP

What It does

This animates expertise items on hover, switching images and texts.

    // ============================================
    // EXPERTISE SECTION WITH GSAP
    // ============================================

    function initExpertiseAnimations() {
        const expertiseFiguresContainer = document.querySelector('.home_expertise_figures');
        const expertiseInnerContainer = document.querySelector('.home_expertise_inner');
        const expertiseTextWrap = document.querySelector('.home_expertise_text_wrap');
        const expertiseTextItems = expertiseTextWrap?.querySelectorAll('.home_expertise_text') || [];

        if (!expertiseFiguresContainer || !expertiseInnerContainer || !expertiseTextItems.length) return;

        const expertiseImageElements = expertiseFiguresContainer.querySelectorAll('.home_expertise_image');
        const expertiseItemElements = expertiseInnerContainer.querySelectorAll('.home_expertise_item');

        // Initialize with GSAP
        gsap.set(expertiseImageElements, {
            position: 'absolute',
            top: 0,
            left: 0,
            autoAlpha: 0,
            zIndex: 0,
            scale: 1
        });

        gsap.set(expertiseImageElements[0], {
            autoAlpha: 1,
            zIndex: 2,
            scale: 1
        });

        expertiseItemElements[0].classList.add('is-active');
        expertiseTextItems[0].classList.add('is-active');
        gsap.set(expertiseTextItems[0], { y: 0, autoAlpha: 1 });

        gsap.set(Array.from(expertiseTextItems).slice(1), { y: 40, autoAlpha: 0 });

        // Setup hover animations with GSAP
        expertiseItemElements.forEach((item, itemIndex) => {
            item.addEventListener('mouseenter', () => {
                expertiseItemElements.forEach(el => el.classList.remove('is-active'));
                item.classList.add('is-active');

                const expertiseImageTransitionTL = gsap.timeline();

                expertiseImageTransitionTL.to(expertiseImageElements, {
                    autoAlpha: 0,
                    zIndex: 0,
                    scale: 1,
                    duration: 0.3,
                    ease: 'power2.inOut'
                });

                expertiseImageTransitionTL.fromTo(
                    expertiseImageElements[itemIndex],
                    { autoAlpha: 0, scale: 1.3, zIndex: 2 },
                    { autoAlpha: 1, scale: 1, zIndex: 2, duration: 0.5, ease: 'power2.out' },
                    '-=0.2'
                );

                expertiseTextItems.forEach((text, index) => {
                    if (index === itemIndex) {
                        text.classList.add('is-active');
                        gsap.to(text, { y: 0, autoAlpha: 1, duration: 0.5, ease: 'power2.out' });
                    } else {
                        text.classList.remove('is-active');
                        gsap.to(text, { y: 40, autoAlpha: 0, duration: 0.5, ease: 'power2.out' });
                    }
                });
            });
        });
    }
Code Block 4

Element Map

  • .home_expertise_figures: Images container; images scale/fade on hover.

  • .home_expertise_image: Individual images.

  • .home_expertise_inner: Items container.

  • .home_expertise_item: Hoverable items.

  • .home_expertise_text_wrap: Texts container.

  • .home_expertise_text: Texts slide in/out.

HTML Requirements

Div home_expertise_figures with multiple home_expertise_image, home_expertise_inner with home_expertise_item, home_expertise_text_wrap with matching home_expertise_text.

Customizing Key Variables

  • Fade duration: Change duration: 0.3 to duration: 0.6 for slower hide.

    expertiseImageTransitionTL.to(expertiseImageElements, {
        autoAlpha: 0,
        zIndex: 0,
        scale: 1,
        duration: 0.6,
        ease: 'power2.inOut'
    });
  • Scale duration: Change duration: 0.5 to duration: 0.7 for slower reveal.

    expertiseImageTransitionTL.fromTo(
        expertiseImageElements[itemIndex],
        { autoAlpha: 0, scale: 1.3, zIndex: 2 },
        { autoAlpha: 1, scale: 1, zIndex: 2, duration: 0.7, ease: 'power2.out' },
        '-=0.2'
    );
  • Ease: 'power2.out' → 'bounce.out'.

Removing Animations

  • Comment/Remove: The code from page settings that are shown in Code Block 4

Location Section with GSAP

What It does

This animates location items on hover, switching images.

    // ============================================
    // LOCATION SECTION WITH GSAP
    // ============================================

    function initLocationAnimations() {
        const locationTextElements = document.querySelectorAll('.location_text');
        const locationImageContainer = document.querySelector('.home_location_image_list');
        const locationImageItems = document.querySelectorAll('.home_location_image_item');

        if (!locationTextElements.length || !locationImageContainer || !locationImageItems.length) return;

        // Initialize with GSAP
        gsap.set(locationImageItems, {
            position: 'absolute',
            top: 0,
            left: 0,
            autoAlpha: 0,
            scale: 0.6
        });

        locationTextElements.forEach(textElement => {
            const locationTitleElement = textElement.querySelector('.location_title');
            if (locationTitleElement) locationTitleElement.classList.remove('is-active');
        });

        // Setup hover animations with GSAP
        locationTextElements.forEach((textElement, textIndex) => {
            textElement.addEventListener('mouseenter', () => {
                locationTextElements.forEach(el => {
                    const title = el.querySelector('.location_title');
                    if (title) title.classList.remove('is-active');
                });

                const hoveredLocationTitle = textElement.querySelector('.location_title');
                if (hoveredLocationTitle) hoveredLocationTitle.classList.add('is-active');

                const locationImageTL = gsap.timeline();

                locationImageTL.to(locationImageItems, {
                    autoAlpha: 0,
                    scale: 0.6,
                    duration: 0.3,
                    ease: 'power2.inOut'
                });

                locationImageTL.fromTo(
                    locationImageItems[textIndex],
                    { autoAlpha: 0, scale: 0.6 },
                    { autoAlpha: 1, scale: 1, duration: 0.5, ease: 'power2.out' },
                    '-=0.15'
                );
            });
        });
    }
Code Block 5

Element Map

  • .location_text: Hoverable text elements.

  • .location_title: Titles activate on hover.

  • .home_location_image_list: Images container.

  • .home_location_image_item: Images scale/fade on hover.

HTML Requirements

Multiple location_text divs each with location_title, home_location_image_list with matching home_location_image_item.

Customizing Key Variables

  • Hide duration: Change duration: 0.3 to duration: 0.5 for slower fade out.

    locationImageTL.to(locationImageItems, {
        autoAlpha: 0,
        scale: 0.6,
        duration: 0.5,
        ease: 'power2.inOut'
    });
  • Reveal duration: Change duration: 0.5 to duration: 0.8 for slower scale in.

    locationImageTL.fromTo(
        locationImageItems[textIndex],
        { autoAlpha: 0, scale: 0.6 },
        { autoAlpha: 1, scale: 1, duration: 0.8, ease: 'power2.out' },
        '-=0.15'
    );

Removing Animations

  • Comment/Remove: The code from page settings that are shown in Code Block 5

Initialize All Animations on Page Load

What It does

This runs all functions when page loads.

    // ============================================
    // INITIALIZE ALL ANIMATIONS ON PAGE LOAD
    // ============================================
    document.addEventListener('DOMContentLoaded', function () {
        initHeroSliderAnimations();
        initTestimonySliderAnimations();
        initExpertiseAnimations();
        initLocationAnimations();
    });
Code Block 6

Element Map

  • No new elements; calls other functions.

Removing Animations

  • Comment out function calls: // initHeroSliderAnimations(); etc.

Counter Animation with GSAP

What It does

This animates counters to count up from 0 on scroll.

HTML Requirements

Elements like <div class="counter">1234</div> with target number as text. Note: Don't includ the comma in original content in Webflow.

   // ============================================
    // COUNTER ANIMATION WITH GSAP
    // ============================================

    function initCounterAnimations() {
        const counterElements = document.querySelectorAll(".counter");

        counterElements?.forEach(counterItem => {
            gsap.from(counterItem, {
                textContent: 0,
                duration: 4,
                ease: "power1.in",
                snap: { textContent: 1 },
                scrollTrigger: {
                    trigger: counterItem,
                    start: "top 95%",
                    once: true
                },
                onUpdate: function () {
                    const counterValue = Math.ceil(parseInt(counterItem.textContent) || 0);
                    counterItem.textContent = counterValue.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",");
                }
            });
        });
    }

    // ============================================
    // INITIALIZE ANIMATIONS ON PAGE LOAD
    // ============================================
    document.addEventListener('DOMContentLoaded', function () {
        initCounterAnimations();
    });
Code Block 7

Element Map

  • .counter: Text animates from 0 to value, with commas.

Customizing Key Variables

  • Duration: 4 → 6 for slower.

    duration: 6
  • Reveal: 0.5 → 0.7.

    duration: 0.7
  • Ease: "power1.in" → "power2.inOut".

    ease: "power2.inOut"
  • Start: "top 95%" → "top 80%" for delayed trigger.

    start: "top 80%"

Removing Animations

  • Comment/Remove: The code from site settings that are shown in Code Block 7

A living room filled with furniture and plants.
Interessiert?
Termin vereinbaren.

Soll ich auch auf deine Objekte einen Blick werfen?