webdevpuneet.com

Scroll Skew Velocity — Free GSAP ScrollTrigger Skew Effect

Scroll Skew Velocity · Scroll · Plain HTML, CSS & JS · Live preview

Copy & paste

Source Code

<section class="sk-intro"><h1>Scroll fast ↓</h1><p>The cards skew with your scroll velocity.</p></section>
<section class="sk-list" id="skList">
  <article class="sk-card skew"><span>01</span><h3>Momentum</h3></article>
  <article class="sk-card skew"><span>02</span><h3>Velocity</h3></article>
  <article class="sk-card skew"><span>03</span><h3>Inertia</h3></article>
  <article class="sk-card skew"><span>04</span><h3>Friction</h3></article>
  <article class="sk-card skew"><span>05</span><h3>Drift</h3></article>
  <article class="sk-card skew"><span>06</span><h3>Glide</h3></article>
</section>
<section class="sk-outro"><p>Skew eases back to zero when you stop.</p></section>

Extend with AI

Take This Snippet Further With AI

The AI prompt for this one is for Patreon supporters ($3 a month, 7 days free), along with a site with no ads. Supporters enter the passcode once and it is remembered in this browser.

· Become a supporter

What's included

Features

Velocity read
ScrollTrigger getVelocity per frame.
Clamped skew
Hard limit keeps shear tasteful.
quickTo setters
Reusable, no tween-per-frame cost.
Smooth easing
power3 ramps and settles the skew.
Auto reset
Returns to 0 when velocity drops.
Direction-aware
Leans the way it scrolls.
GPU transform
skewY composites, no reflow.
Scales to many
One velocity read drives all cards.

About this UI Snippet

Scroll Skew Velocity — Cards That Lean Into Your Scroll Speed

Screenshot of the Scroll Skew Velocity snippet rendered live

Velocity skew is the tactile effect where list items shear slightly in the direction you're scrolling and snap upright when you stop — the "the page has momentum" feel from award-winning sites. This snippet builds it with GSAP and ScrollTrigger (from a CDN), reading raw scroll velocity and mapping it to a live skew.

Reading scroll velocity

A global ScrollTrigger with an onUpdate callback runs on every scroll frame and calls self.getVelocity(), which returns the current scroll speed in pixels per second — positive scrolling down, negative scrolling up. That number is the engine of the effect: fast scrolling yields a big value, easing off yields a small one, and stopping yields zero. No manual delta tracking or timing is needed; ScrollTrigger measures it.

Mapping velocity to skew

The raw velocity is divided down (/ -260) to a sensible degree range and passed through gsap.utils.clamp(-14, 14) so even a violent flick can't shear the cards past a tasteful maximum. The negative divisor flips the sign so the cards lean the way that reads as "trailing" the scroll. This clamp-and-scale step is what keeps the effect feeling like physics rather than a glitch.

quickTo for cheap per-frame updates

Instead of creating a new tween every frame (expensive and janky), each card gets a gsap.quickTo(el, 'skewY', ...) setter — a reusable function that smoothly interpolates that one property toward whatever value you pass. On each scroll update the code calls every setter with the current skew, and GSAP eases the actual skewY toward it with a short power3 duration. That built-in easing is what makes the skew ramp up and settle smoothly, and crucially returns the cards to 0 when velocity drops, with no separate "reset" logic.

Why this is the right pattern

Skewing on scroll naively (writing transform directly from velocity) looks twitchy because raw velocity is noisy. Routing it through quickTo's interpolation low-passes the motion, and the clamp bounds it — together they turn a jittery signal into a fluid lean. ScrollTrigger's getVelocity removes the need to compute speed by hand across frames.

Composited and contained

Only transform (skewY) animates, so the browser composites the cards on the GPU with no reflow, and will-change: transform promotes them. The effect scales to many items because every card shares the same single velocity read per frame.

Customizing it

Change the divisor for more or less shear, the clamp for a tighter or looser limit, the quickTo duration for snappier or floatier recovery, or skew on skewX for a horizontal feel. Pair it with a scroll velocity marquee, a scroll reveal grid, or an animated list.

Step by step

How to Use

  1. 1
    Add the GSAP CDNsInclude gsap and ScrollTrigger from the CDN panel.
  2. 2
    Paste HTML, CSS, and JSA list of cards renders between spacers.
  3. 3
    Scroll quicklyThe cards skew in the scroll direction.
  4. 4
    Stop scrollingThe skew eases back to zero.
  5. 5
    Tune the shearChange the velocity divisor and clamp.
  6. 6
    Tune the recoveryAdjust the quickTo duration.

Real-world uses

Common Use Cases

Momentum-feel feature lists
Add a kinetic quality to an animated list, where cards shear in the direction of scrolling and settle upright when you stop.
Marquee pairings
Pair with a scroll velocity marquee so that both text and cards visibly respond to how fast the visitor is scrolling.
Gallery and grid lean
Make a scroll reveal grid lean with the scroll, using a hard clamp on the skew so the shear stays tasteful.
Portfolio energy
Energise a portfolio filter grid with quickTo setters that reuse tweens instead of creating one per frame.
Editorial and landing sections
Give body copy or a feature cards section a kinetic feel, with power3 easing ramping the skew up and settling it back.
Related: Scrollama Scrollytelling
See the Scrollama Scrollytelling for a related scroll pattern worth pairing with this one.

Got questions?

Frequently Asked Questions

A global ScrollTrigger's onUpdate runs each scroll frame and calls self.getVelocity(), which returns the scroll speed in pixels per second — positive down, negative up. Fast scrolling gives a large value, easing off gives a small one, and stopping gives zero, so ScrollTrigger supplies the velocity without manual delta or timing code.

The raw velocity is divided down and clamped to a max of about 14 degrees, then passed to per-card gsap.quickTo setters. quickTo interpolates the skewY toward the new value with a short power3 ease, which low-passes the noisy signal into a fluid lean and naturally returns the cards to zero when velocity drops — no separate reset logic.

Writing the transform straight from velocity looks twitchy because the signal is jittery, and creating a fresh tween every frame is expensive. quickTo builds one reusable setter per property that smoothly eases toward whatever value you pass, giving cheap per-frame updates and built-in easing in one — the recommended GSAP pattern for continuous scroll-driven values.

Yes. Only skewY, a transform, animates, so the browser composites the cards on the GPU with no reflow, and will-change promotes them. There is a single getVelocity read per frame shared by all cards, so adding more items costs only the quickTo setter calls, which are lightweight.

In a mount effect, register ScrollTrigger, build quickTo setters for the card refs, and create one ScrollTrigger whose onUpdate clamps getVelocity and calls the setters. Return a cleanup that kills the ScrollTrigger and reverts the GSAP context so it stops on unmount. The CSS ports unchanged; keep the setters in a ref so they persist across renders.