Motion

Scroll

One smooth scroll for the whole app. Lenis glides the page; GSAP's clock drives it; ScrollTrigger reads it. Everything that reacts to scroll goes through that one chain.

The scroll engine

These numbers update live as you scroll this page.

Scrolled0px
Speed0
Page read0%
Direction—
new Lenis({"autoRaf": false, "anchors": false, "lerp": 0.09, "wheelMultiplier": 0.9})
gsap.ticker.add((t) => lenis.raf(t * 1000)) · gsap.ticker.lagSmoothing(0) · lenis.on('scroll', ScrollTrigger.update)

Scroll rules

  1. One loop. Lenis never runs its own animation frame (autoRaf: false); GSAP's ticker feeds it.
  2. scrub: true, never a number. Lenis already smooths the scroll; a numeric scrub smooths it twice and the page feels late.
  3. No ScrollTrigger snap. It fights the glide. Jump with scrollToTarget() instead.
  4. Entrances play once. Content reveals the first time it reaches the screen, then stays put. Scrolling back never hides it.
  5. Inner scroll areas opt out. Menus, lists and sheets that scroll carry data-lenis-prevent; sideways strips carry data-lenis-prevent-horizontal.
  6. Overlays stop the page. Dialogs, drawers and the palette call lockScroll() and give it back on close.
  7. Phones scroll natively. Touch keeps the browser's own momentum; only wheel and trackpad are smoothed.

Scroll to

Jumps glide through Lenis (1.4s); they never use window.scrollTo.

Scrubbed progress

Tied to scroll with scrub: true — it moves exactly with the page, forward and back.

This section's progress through the screen

Scroll reveal

Each word sharpens as the paragraph rises; the block untilts at the same time (website About section).

PropValuesDefaultWhat it does
textstring—The paragraph
baseOpacity / blurStrengthnumber · px0.1 · 4How faint and blurred words start
baseRotationdegrees3The tilt the block straightens from
staggernumber0.05How far apart the words sharpen

Reveal on enter

use:reveal — content slides up and fades in once, the first time it arrives (React Bits AnimatedContent).

Jobs on site0
Crew-days booked0
Invoices paid0
PropValuesDefaultWhat it does
distance / direction / reversepx · 'vertical' | 'horizontal' · bool100 · vertical · falseWhere it comes from
duration / ease / delays · ease · s0.8 · power3.out · 0The move
staggers0Reveal each child in turn
scale / blur / initialOpacitynumber · px · 0–11 · 0 · 0Extra ways in
threshold0–10.1How much must be visible first