New
Introducing evidence-based review drafts
Learn more
Learn more
Instructions

Instructions

This template uses custom-built GSAP-powered systems to create smooth, responsive, and performant animations in Webflow.

Smooth page scroll

How it works

This animation adds smooth, inertia-based page scrolling using Lenis, with GSAP ScrollTrigger registered for scroll-based animations.

The script loads the Lenis stylesheet and library from a CDN, then initializes a Lenis instance once the page has loaded. It skips loading anything that is already on the page, so nothing is duplicated.

Lenis runs on a requestAnimationFrame loop and eases the page toward the target scroll position instead of jumping. Anchor links (a[href^="#"]) are intercepted and scrolled to smoothly.

Customization options

  • Adjust scroll smoothness using lerp.
    • Lower value → smoother, slower-feeling scroll
    • Higher value → snappier, more direct scroll
    • Recommended: 0.05 to 0.15
  • Modify mouse wheel speed using wheelMultiplier.
    • Default: 1
    • Higher value → faster scroll per wheel tick
  • Modify touch scroll speed using touchMultiplier.
    • Default: 1.5
  • Enable looping scroll using infinite.
    • false → page stops at the top and bottom (default)
  • Keep autoResize: true so Lenis recalculates page height when the window resizes.
  • Adjust anchor link scrolling using duration (default 1.5 seconds) and offset (default 0).
    • Use a negative offset (e.g. -80) to leave room for a fixed navbar
  • Change the Lenis version by updating 1.1.13 in both CDN URLs.
  • Control scrolling from anywhere with the global instance:
    • window.lenis.stop() → pause scrolling (e.g. when a modal opens)
    • window.lenis.start() → resume scrolling
    • window.lenis.scrollTo("#section-id") → scroll to a section

Features

  • Smooth, inertia-based page scroll
  • Lenis stylesheet and library loaded automatically from the CDN
  • Duplicate-load protection for the CSS and script
  • Smooth anchor link scrolling with adjustable duration
  • Separate speed control for wheel and touch input
  • Error logging if the Lenis library fails to load
  • Global window.lenis instance for custom control
  • GSAP ScrollTrigger registered and ready for scroll animations
  • Lightweight, with no extra setup in the Designer

Requirements

  • Load GSAP and ScrollTrigger before this script, otherwise gsap.registerPlugin(ScrollTrigger) will throw an error.
  • Add this to Page Settings → Custom Code → Before </body> (or the site-wide footer code) in Webflow.
  • It only runs on the published or staging site, not in the Designer.

Counter animation

How it works

This animation counts a number up from 0 to a target value when the element scrolls into view, using GSAP and ScrollTrigger.

The script finds every element with the data-counter attribute and reads its value (for example 250+). It splits the value into a number (250) and a suffix (+), then animates a temporary value from 0 to the target.

On every frame, the element's text is updated with the rounded number followed by the suffix. The animation plays once, when the element reaches 85% of the viewport height, and does not repeat.

Customization options

  • Use attribute data-counter for each counter element.
    • Example: <span data-counter="250+"></span>
    • Any suffix is kept, e.g. %, +, k, M
  • Adjust counting speed using duration.
    • Lower value → faster count
    • Higher value → slower count
    • Default: 2 seconds
  • Change easing using ease: "power1.out" for a natural slowdown near the end.
    • Try power2.out or power3.out for a stronger slowdown
    • Use none for a constant speed
  • Adjust when the counter starts using start: "top 85%".
    • Lower percentage (e.g. top 70%) → starts later, deeper in the viewport
    • Higher percentage (e.g. top 95%) → starts earlier
  • Keep once: true so the counter plays only one time.
    • Remove it (and change toggleActions to "play none none reset") to replay on every scroll
  • Control number formatting with toLocaleString.
    • useGrouping: false → 1000
    • useGrouping: true → 1,000
  • Start from a different number by changing value: 0 in the obj object.

Features

  • Scroll-triggered counting, so it only plays when the number is visible
  • Works with any number of counters on the page
  • Suffix support (+, %, k, etc.) with no extra setup
  • Commas in the attribute value are handled (e.g. 1,200+)
  • Plays once, with no repeated animation
  • Smooth ease-out that slows near the final number
  • Lightweight, with no external libraries beyond GSAP and ScrollTrigger
  • Ideal for stats, achievements, client counts, and results sections

Text appearance

How it works

This animation reveals a heading word by word on scroll. Each word starts blurred, faded, slightly enlarged, and pushed down, then sharpens into place one after another, using GSAP and ScrollTrigger.

The script finds every element with the data-heading attribute and splits its text into individual words, wrapping each word in a span. Elements inside the heading (such as a colored or bold word) are kept intact and treated as one unit.

When the heading reaches 90% of the viewport height, the words animate in with a stagger. Scrolling back up reverses the animation. The effect runs only on screens 992px and wider. Below that, the original heading markup is restored and the text shows normally.

Customization options

  • Use attribute data-heading on each heading you want animated.
    • Example: <h2 data-heading>We're building a smarter way to run business</h2>
  • Adjust reveal speed per word using duration.
    • Lower value → faster reveal
    • Higher value → slower reveal
    • Default: 0.6 seconds
  • Adjust the delay between words using stagger.
    • Lower value → words appear almost together
    • Higher value → words appear one by one
    • Default: 0.12 seconds
  • Change easing using ease: "power2.out" for a soft landing.
    • Try power3.out for a stronger slowdown
    • Use back.out(1.7) for a slight overshoot
  • Adjust when the animation starts using start: "top 90%".
    • Lower percentage (e.g. top 75%) → starts later, deeper in the viewport
    • Higher percentage (e.g. top 95%) → starts earlier
  • Change the replay behavior using toggleActions.
    • "play none none reverse" → plays on enter, reverses when scrolling back above
    • "play none none none" → plays once and stays
  • Modify the starting look of each word (set in the script and matched by the end values in the tween):
    • blur(10px) → amount of blur
    • opacity 0.3 → starting transparency
    • scale(1.15) → starting size
    • translateY(0.75rem) → starting vertical offset
  • Change the breakpoint by updating (min-width: 992px) in matchMedia.
    • Use (min-width: 0px) to run on all screen sizes

Features

  • Word-by-word blur reveal with a smooth stagger
  • Scroll-triggered, so it plays when the heading is visible
  • Reverses when scrolling back up
  • Keeps inner elements (colored, bold, or linked words) intact
  • Runs on desktop only, with the original text restored on smaller screens
  • Automatic cleanup when the viewport changes, with no leftover spans or triggers
  • Works with any number of headings on the page
  • Lightweight, with no external libraries beyond GSAP and ScrollTrigger
  • Ideal for section headings, hero titles, and statements

Card appearance

How it works

This animation reveals cards as they scroll into view. Each card starts blurred, transparent, slightly smaller, and offset to one side or below, then slides into place and sharpens, using GSAP and ScrollTrigger.

The script looks for elements carrying one of seven attributes (card-1 to card-7). Each attribute has its own entry direction: cards 1, 4, and 7 come in from the left, cards 3 and 6 from the right, and cards 2 and 5 rise from below. When a card reaches 90% of the viewport height, it animates in. Scrolling back up reverses the animation.

The effect runs only on screens wider than 991px. On tablet and mobile, the script exits early and the cards show normally.

Customization options

  • Use attributes card-1 to card-7 on each card you want animated.
    • Example: <div card-1>...</div>
    • Several elements can share the same attribute, and each one animates on its own trigger
  • Change the entry direction in the directions object.
    • x: -60 → slides in from the left
    • x: 60 → slides in from the right
    • y: 60 → rises from below
    • y: -60 → drops from above
    • Larger values → longer travel distance
  • Adjust animation speed using duration.
    • Lower value → faster reveal
    • Higher value → slower reveal
    • Default: 0.9 seconds
  • Change easing using ease: "power3.out" for a smooth, strong slowdown.
    • Try power2.out for a softer landing
    • Use back.out(1.4) for a slight overshoot
  • Adjust the starting look of each card:
    • blur(12px) → amount of blur
    • opacity: 0 → starting transparency
    • scale: 0.96 → starting size
  • Adjust when the animation starts using start: "top 90%".
    • Lower percentage (e.g. top 75%) → starts later, deeper in the viewport
    • Higher percentage (e.g. top 95%) → starts earlier
  • Change the replay behavior using toggleActions.
    • "play none none reverse" → plays on enter, reverses when scrolling back above
    • "play none none none" → plays once and stays
  • Change the breakpoint by updating window.innerWidth <= 991.
    • Remove the line to run on all screen sizes
  • Add more directions by adding a new key (e.g. "card-8": { x: 0, y: -60 }).

Features

  • Scroll-triggered reveal with blur, fade, scale, and slide
  • Seven preset entry directions that alternate for a varied layout
  • Each card has its own trigger, so cards animate independently
  • Supports multiple elements per attribute
  • Reverses when scrolling back up
  • Runs on desktop only, with cards shown normally on smaller screens
  • Lightweight, with no external libraries beyond GSAP and ScrollTrigger
  • Ideal for feature cards, service grids, pricing cards, and bento layouts

Awards hover

How it works

This animation turns the awards list into a hover-driven highlight list where one row is active at a time, using GSAP.

The script finds every .rt-awards-item and, for each one, its matching line (.rt-line-v4), arrow (.rt-arrow-wrapper), and badge (.rt-award-badge-v1). These are matched by position, so the 1st item uses the 1st line, arrow, and badge, and so on.

On load, the 3rd item is set active instantly with no animation. When the cursor enters any item, that item becomes active: its line grows to full width, its arrow fades in, and its badge fades in. All other items reset, with the line shrinking to 0%, and the arrow and badge fading out.

Customization options

  • Use these class names in the Designer:
    • .rt-awards-item for each award row
    • .rt-line-v4 for the line inside each row
    • .rt-arrow-wrapper for the arrow inside each row
    • .rt-award-badge-v1 for the badge inside each row (optional)
  • Choose which item starts active using defaultIndex.
    • 0 → first item
    • 2 → third item (default)
  • Adjust line speed using duration: 0.5 (the dur value).
    • Lower value → faster fill
    • Higher value → slower fill
  • Adjust arrow fade speed using duration: 0.35.
  • Adjust badge fade speed using duration: 0.4.
  • Change easing using ease: "power2.out".
    • Try power3.out for a stronger slowdown
  • Change the line direction using width.
    • Set the line's transform origin to left or right in the Designer to control which side it grows from
  • Change the inactive look by editing the "0%" and 0 values.
    • Use opacity: 0.3 for a dimmed arrow or badge instead of hidden
  • Set animate to false in setActive() to make changes instant.

Features

  • One row active at a time
  • Smooth line fill, arrow fade, and badge fade on hover
  • Default active row set instantly on load, with no flash
  • Works with any number of award rows
  • Badge is optional
  • Lightweight, with no external libraries beyond GSAP