CustomBounce
CustomBounce is a GSAP easing plugin that builds a tunable bounce curve you shape yourself, instead of the one fixed shape you get from the built-in `bounce.out`. You set how bouncy it is with `strength`, whether the element lands back where it started with `endAtStart`, and how long it squashes on impact with `squash`, and CustomBounce hands you back a named ease you can drop into any tween.
Updated July 1, 2026
How CustomBounce works
CustomBounce extends CustomEase, so it works by generating a real easing curve at create time and registering it under a name you choose. You call CustomBounce.create(id, vars) once, then reference that id as a string in the ease of any tween. The vars object is where the tuning lives: strength (0 to 1) sets how many times it bounces, squash adds a beat where the element looks stuck to the floor between bounces, and endAtStart makes it leave and return to its starting value.
That graph is GSAP's built-in bounce.out, and it's a single fixed shape: three decreasing bounces, no squash, always settling at the end. CustomBounce is the version you get to reshape. Turn strength up toward 0.9 and you get many small bounces; drop it toward 0.3 and you get one or two heavy ones. The curve you'd see for a high-strength CustomBounce has more, tighter oscillations packed near the end than the graph above.
CustomEase is required
CustomEase, so you have to register both (gsap.registerPlugin(CustomEase, CustomBounce)). Registering only CustomBounce is the most common reason a myBounce ease silently falls back to power1.out.Use it for
- A ball, badge, or card that drops in and physically settles with more than one bounce
- A number counter that lands on its final value and bounces to rest
- Adding real squash and stretch on impact (the
squashoption plus the paired squash ease drivingscaleX/scaleY) - A throw-up-and-land move where the object leaves and returns to the same spot (
endAtStart: true) - Any bounce where the fixed
bounce.outshape feels too generic and you need to dial the weight
Use something else when
- You want one clean overshoot, not a settling bounce, use
back.out(1.7)(no plugin needed, ships with core) - You want a springy wobble that oscillates past the target and back, use
elastic.out(1, 0.3) - The motion is UI feedback (button, toggle, hover), use
expo.outat a short duration, a bounce reads as playful, not responsive - You need a bespoke curve that isn't a bounce at all, draw it with
CustomEase.create()directly - The user has
prefers-reduced-motionset, drop the bounce entirely rather than shipping a softened version
Bounce is exactly what reduced-motion is for
prefers-reduced-motion passed 50% adoption on mobile sites in 2024, up from 34% in 2022 (Web Almanac 2024, Accessibility chapter), so gate every CustomBounce tween behind gsap.matchMedia() and hand reduced-motion users a plain fade or an instant set.Where a bounce ease fits in Annnimate components
Both of these components already expose the ease as a data-anm-ease config, so a CustomBounce ease drops straight in without touching the animation logic. Neither ships with CustomBounce by default, they use a lighter single-overshoot spring, and the plugin is the upgrade path when you want a real settling bounce:
- Popping Text ships with
back.out(1.7)so each character pops in with one overshoot. Swap the ease for astrength: 0.5CustomBounce and the characters settle with a couple of real bounces instead of a single spring - Counter counts to its target with
power3.inOut. Feed it a CustomBounce ease and the number overshoots and bounces onto its final value, which reads well for stat blocks and score reveals
Tuning tip
strength around 0.4 to 0.6 for UI. Above 0.8 you get a long tail of tiny bounces that looks cartoonish on text and counters. Add squash: 2 only when the element visibly hits a surface, on a floating counter it just looks like a glitch.See it running in production
Common questions
- Why does my CustomBounce ease not work / fall back to a linear-ish curve?
- You almost certainly registered CustomBounce but not CustomEase. CustomBounce extends CustomEase and can't build its curve without it. Register both:
gsap.registerPlugin(CustomEase, CustomBounce). Also confirm the string in your tween'seaseexactly matches theidyou passed toCustomBounce.create(), a typo makes GSAP fall back to the default ease with no error. - When do I need CustomBounce instead of the built-in bounce.out?
- Use
bounce.outwhen its default shape looks right, it needs no plugin and no setup. Reach for CustomBounce when you want to change the shape: fewer or more bounces (strength), a squash/stuck beat between bounces (squash), or a bounce that returns to its start (endAtStart).bounce.outgives you exactly one look; CustomBounce gives you a whole family. - What does endAtStart actually do?
endAtStart: truemakes the ease end back at the value it started from, so you get an object sitting on the ground, leaping up, and bouncing back down to a stop. It's the config you want for a throw-and-land where the start and end positions are the same, rather than a drop where the element travels from A to B.- How do I get the squash-and-stretch on impact?
- Set
squashon the create call (2 is a good starting point) and give it asquashID. That registers a SECOND ease. You run your position tween with the bounce ease, and a separate tween onscaleX/scaleYwith the squash ease andtransformOrigin: "center bottom". The two eases are timed so the element flattens exactly when it hits. - Is CustomBounce free, or is it a Club GSAP plugin?
- It's free. Every GSAP plugin, including CustomBounce and CustomEase, has been fully free for any use since GSAP 3.13 (mid-2024), after Webflow acquired GreenSock. You just import and register it like any core plugin, no membership or license key.
circ.in, circ.out, circ.inOut) whose curve traces a quarter circle, so the motion is nearly flat through the middle and bends hard at one or both ends.NextCustomEaseCustomEase is a GSAP plugin that lets you author any easing curve you want, defined either by an SVG path string or by control points.