Smooth scrolling effect for the template using Lenis with GSAP integration for precise scroll updates and animations.
<link rel="stylesheet" href="https://unpkg.com/lenis@1.3.15/dist/lenis.css" />
<script src="https://unpkg.com/lenis@1.3.15/dist/lenis.min.js"></script>
<script>
const lenis = new Lenis({ duration: 1.4 });
lenis.on('scroll', ScrollTrigger.update);
gsap.ticker.add((time) => {
lenis.raf(time * 1000);
});
gsap.ticker.lagSmoothing(0);
</script>
High-performance animated counters built with GSAP, offering precise timing, smooth transitions, and seamless scroll-triggered activation.
<script>
// /*
// ========================================
// GSAP COUNTER (Webflow Marketplace Ready)
// ========================================
// HOW IT WORKS:
// - Add class: data-counter
// - Add attribute: data-target="100"
// - Optional: data-decimal="true"
// EXAMPLE:
// <div data-counter data-target="250"></div>
// <div data-counter data-target="2.5" data-decimal="true"></div>
// EDIT OPTIONS:
// - duration → animation speed
// - start → scroll trigger position
// ========================================
// */
document.addEventListener('DOMContentLoaded', function () {
// Safety check (important for Marketplace)
if (typeof gsap === 'undefined' || typeof ScrollTrigger === 'undefined') {
console.warn('GSAP or ScrollTrigger not loaded');
return;
}
gsap.registerPlugin(ScrollTrigger);
const counters = document.querySelectorAll('[data-counters]');
counters.forEach((counter) => {
let target = parseFloat(counter.getAttribute('data-target')) || 0;
let isDecimal = counter.getAttribute('data-decimal') === 'true';
// Accessibility: Reduced motion support
if (window.matchMedia('(prefers-reduced-motion: reduce)').matches) {
counter.textContent = target;
return;
}
let obj = {
val: 0,
};
gsap.to(obj, {
val: target,
// EDIT: Animation duration
duration: 4,
ease: 'power2.out',
scrollTrigger: {
trigger: counter,
// EDIT: Trigger position
start: 'top 85%',
once: true,
},
onUpdate: () => {
counter.textContent = isDecimal ? obj.val.toFixed(1) : Math.floor(obj.val);
},
});
});
});
</script>