

This provides smooth scrolling across the entire template. To turn off just comment out this code.
<!-- Lenis CSS -->
<link rel="stylesheet" href="https://unpkg.com/lenis@1.1.20/dist/lenis.css">
<!-- Lenis JS -->
<script src="https://unpkg.com/lenis@1.3.1/dist/lenis.min.js"></script>
<script>
(function () {
function initCounterAnimation() {
if (
typeof gsap === "undefined" ||
typeof ScrollTrigger === "undefined"
) {
return;
}
gsap.registerPlugin(ScrollTrigger);
document.querySelectorAll('[class*="wf-counter"]').forEach(function (counter) {
var textEl = counter.querySelector("*") || counter;
var original = textEl.textContent.trim();
var match = original.match(/^([^0-9]*)([0-9.,]+)(.*)$/);
if (!match) return;
var prefix = match[1];
var numberPart = match[2].replace(/,/g, "");
var suffix = match[3];
var hasDecimal = numberPart.indexOf(".") !== -1;
var target = parseFloat(numberPart);
if (isNaN(target)) return;
var obj = { value: 0 };
gsap.to(obj, {
value: target,
duration: 1.2,
ease: "power1.out",
scrollTrigger: {
trigger: counter,
start: "top 90%",
once: true
},
onUpdate: function () {
var currentValue = hasDecimal
? obj.value.toFixed(1)
: Math.floor(obj.value).toLocaleString();
textEl.textContent = prefix + currentValue + suffix;
}
});
});
}
function initSmoothScroll() {
if (
typeof Lenis === "undefined" ||
!window.matchMedia("(min-width: 768px)").matches
) {
return;
}
var lenis = new Lenis({
duration: 0.8,
smoothWheel: true,
smoothTouch: false,
allowNestedScroll: true,
easing: function (t) {
return 1 - Math.pow(1 - t, 3);
}
});
function raf(time) {
lenis.raf(time);
requestAnimationFrame(raf);
}
requestAnimationFrame(raf);
}
function init() {
initCounterAnimation();
initSmoothScroll();
}
if (document.readyState === "loading") {
document.addEventListener("DOMContentLoaded", init);
} else {
init();
}
})();
</script>An auto-playing GSAP hero slider with image zoom, animated progress, and slide counter.
<!-- Hero Slider -->
<script>
const slides = gsap.utils.toArray(".hero-slide");
const progress = document.querySelector(".hero-slider-progress-fill");
const current = document.querySelector(".hero-slider-current");
let index = 0;
const duration = 4;
gsap.set(slides, { autoAlpha: 0 });
gsap.set(slides[0], { autoAlpha: 1 });
gsap.set(progress, { width: "0%" });
function nextSlide() {
// Hide all slides
gsap.set(slides, { autoAlpha: 0 });
// Show active slide
gsap.set(slides[index], { autoAlpha: 1 });
// Update counter
current.textContent = String(index + 1).padStart(2, "0");
// Reset image scale
gsap.set(slides[index].querySelector("img"), {
scale: 1.1
});
// Reset progress instantly when loop starts again
if (index === 0) {
gsap.set(progress, { width: "0%" });
}
const tl = gsap.timeline({
onComplete: () => {
index++;
if (index >= slides.length) {
index = 0;
}
nextSlide();
}
});
// Image zoom
tl.to(slides[index].querySelector("img"), {
scale: 1,
duration: duration,
ease: "power1.out"
}, 0);
// Progress
tl.to(progress, {
width: `${((index + 1) / slides.length) * 100}%`,
duration: duration,
ease: "none"
}, 0);
}
nextSlide();
</script>