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.
Scramble Text Impact Section (Page Home)
The Scramble Text Animation in the Novra template creates a dynamic text reveal effect where characters briefly scramble before resolving into the original text when the element enters the viewport. This interaction is powered by GSAP ScrollTrigger and ScrambleTextPlugin, and it automatically targets any element with the class .scramble. When the element scrolls into view (around 80% of the viewport), the animation plays and progressively reveals the original text using randomized characters before settling into the final content; when the element scrolls out of view, the animation reverses. To use this effect, simply add the class scramble to any text element such as headings, paragraphs, or labels in Webflow Designer. You can edit the displayed text directly in the element, and the animation will automatically apply without additional setup. The animation settings—such as duration, scramble characters, and speed—can be customized inside the footer script if further adjustments are needed.
<script defer>
document.addEventListener("DOMContentLoaded", () => {
gsap.registerPlugin(ScrollTrigger, ScrambleTextPlugin);
document.querySelectorAll(".scramble").forEach((el) => {
const originalText = el.textContent;
gsap.timeline({
scrollTrigger: {
trigger: el,
start: "top 80%",
end: "bottom 20%",
toggleActions: "play reverse play reverse",
}
})
.to(el, {
duration: 1.2,
scrambleText: {
text: originalText,
chars: "+?84564XERS",
speed: 0.8
}
});
});
});
</script>
Draggable Testimonial Section (Page Home)
The Draggable Testimonial Section on the Home Page allows visitors to explore client feedback through a smooth horizontal drag interaction, creating a more dynamic and modern browsing experience compared to traditional sliders. Users can drag the testimonial list with the mouse on desktop or swipe on mobile devices to navigate between testimonial cards. Each testimonial card typically contains a client image, name, and testimonial text. To edit this section, open the Home Page in Webflow Designer, scroll to the Testimonial Section, and modify the content directly inside each Testimonial Card element. You can update the client information, edit the testimonial text, or duplicate cards to add more testimonials while keeping the content concise to maintain readability and smooth interaction performance.
<script>
// -----TESTI SECTION------
// testi slider
gsap.registerPlugin(Draggable);
const gallery = document.querySelector(".testi-ctn-wrap");
Draggable.create(gallery, {
type: "x",
bounds: ".testi-mask-wrapper", // container element
inertia: true
});
// END Service slider
</script>
CTA Behaviour (Page Home)
The CTA Behaviour in the Home Page hero section of the Novra template is designed to guide users toward the primary action of the website with a clean and responsive interaction. The button includes a subtle hover transition that provides visual feedback when users interact with it, helping increase engagement while maintaining the template’s minimal aesthetic. To edit this CTA, open the Home Page in Webflow Designer, navigate to the Hero Section, then select the CTA Button element. From there you can update the button text, change the link destination, and customize its style or hover interaction from the Style Panel or Interactions Panel. It is recommended to keep the CTA text short and maintain the existing hover animation to preserve the visual consistency of the Novra design system.
<script>
// CTA BEHAVIOR
document.addEventListener("DOMContentLoaded", function () {
const hero = document.querySelector(".cta-wrapper");
const textWrap = document.querySelector(".cta-text-wrap");
const icons = document.querySelectorAll(".cta-icon-wrap");
if (!hero || !textWrap || icons.length === 0) return;
hero.addEventListener("mousemove", function (e) {
const rect = hero.getBoundingClientRect();
const mouseX = e.clientX - rect.left;
const mouseY = e.clientY - rect.top;
const textRect = textWrap.getBoundingClientRect();
const textCenterX = textRect.left - rect.left + textRect.width / 2;
const textCenterY = textRect.top - rect.top + textRect.height / 2;
const dxCenter = mouseX - textCenterX;
const dyCenter = mouseY - textCenterY;
const distanceToText = Math.hypot(dxCenter, dyCenter);
const maxDistance = Math.min(rect.width, rect.height) * 0.5;
const blurStrength = Math.max(0, 1 - distanceToText / maxDistance);
icons.forEach((icon, i) => {
// depth variation
const depth = (i % 5) + 1;
const moveX = (mouseX - rect.width / 2) * 0.03 * depth;
const moveY = (mouseY - rect.height / 2) * 0.03 * depth;
// selang seling blur base
const baseBlur =
i % 3 === 0 ? 8 :
i % 3 === 1 ? 4 :
0;
gsap.to(icon, {
x: moveX,
y: moveY,
filter: `blur(${baseBlur * blurStrength}px)`,
duration: 0.4,
ease: "power2.out"
});
});
});
});
</script>