rough
rough is a GSAP ease from the EasePack plugin that jitters an animation's progress through randomized in-between points instead of moving it smoothly, so a value arrives with a shaky, hand-drawn or glitchy feel. You tune how violent the jitter is with `strength` and how fine-grained it is with `points`.
Updated July 1, 2026
How rough works
rough drops a set of points along the tween's timeline (points, default 20), then shoves each one off the straight line by a random amount scaled by strength (default 1). The tween marches between those points following the template ease (linear by default), so instead of one smooth curve you get a stepped, noisy path from start to finish. More points means faster, finer jitter, more strength means wider deviations from the target.
You pass rough as a configurable string ease. The values inside the parentheses are unquoted, and any you leave out fall back to the defaults.
strength(default 1) - how far each point can deviate. Push it to 2-3 for a violent shake, drop it below 1 for a subtle tremor.points(default 20) - how many jitter points across the tween. Fewer points reads as chunky stutter, more points reads as fine static.taper(defaultnone) -out,in, orbothto fade the roughness toward that end so the value can settle instead of shaking right up to the finish.randomize(defaulttrue) - shuffles the order of the point magnitudes. Setfalseand the deviations decrease steadily instead of scattering.clamp(defaultfalse) - settrueto keep the value inside the 0-1 range so it never overshoots past the target mid-jitter.template(default linear) - an underlying ease the jitter rides on top of, e.g.strength: 1, points: 20, template: power2.outto shake while decelerating.
This is exactly the motion people disable
prefers-reduced-motion exists to kill. That query jumped from 34% of mobile sites in 2022 to over 50% by 2024 (HTTP Archive Web Almanac 2024, Accessibility), so it's now the most-adopted user-preference query on the web. Gate anything rough behind gsap.matchMedia() and swap to a still state or a plain power2.out when reduce is set.Use it for
- Glitch and static text reveals where characters should shudder into place
- Impact shake on a hit, error, or failed-validation state
- Hand-drawn or sketchy wobble on illustrations and SVG
- Flicker on a neon sign, old screen, or loading glyph
- Any moment where the point is that the motion looks unsteady rather than polished
Use something else when
- You want a clean, responsive landing - use
expo.outorpower4.out, not noise - You want a single controlled overshoot - use
back.out(1.7)orelastic.out - You want continuous oscillation that decays smoothly - use
CustomWiggle(a tuned wiggle reads more intentional than random jitter) - You want a physically believable bounce - use
CustomBounce, which models real settling instead of scattering - You only want to shake position - animate
x/ykeyframes on a separate tween and leave the main ease alone
Used in these Annnimate components
rough is the ease you reach for when the motion is supposed to feel restless. Two Annnimate components live in that same register:
- Text Scramble shuffles characters with ScrambleTextPlugin for a glitchy reveal, and a rough ease gives a single transform that same jittery quality without swapping any text
- Random Rotate drops elements onto random angles, and a rough ease on the rotation makes each one shudder toward its resting angle instead of easing in on a clean curve
Tuning tip
points before you touch strength.See it running in production
Common questions
- What's the difference between strength and points in rough()?
strengthcontrols how far the value deviates from the straight line (the amplitude of the jitter),pointscontrols how many jitter steps happen across the tween (the frequency). High strength with low points is a big chunky stutter, low strength with high points is a fine tremor. They're independent, so tune them separately.- Do I need to register a plugin to use rough?
- Yes. rough lives in EasePack, so import RoughEase and register it:
import { RoughEase } from 'gsap/EasePack'thengsap.registerPlugin(RoughEase). Since GSAP 3.13 (mid-2024) EasePack and every other plugin is free, so there's no Club license to worry about. Forgetting to register is the usual reasonease: 'rough(...)'silently falls back to linear. - How do I stop rough from overshooting past the end value?
- Add
clamp: trueto the config. By default the random points can push the value below 0 or above 1, which means an element can jitter past its target and snap back.clamp: truekeeps every point inside the 0-1 range so it only ever shakes toward the destination, never past it. - How do I make a rough animation settle smoothly at the end?
- Use
taper: out. It scales the roughness down toward the finish, so the jitter is strongest at the start and fades to a clean landing. Pair it with atemplateease likepower2.outif you also want the underlying motion to decelerate:rough({ taper: out, template: power2.out }). - Why does my rough ease play the same jitter pattern every time?
- The pattern is baked when the ease is created, not re-rolled per play, so the same config string produces the same curve on every tween that uses it.
randomize: trueonly shuffles the order of the point magnitudes within that one config. If you want a genuinely different shake each time, build a fresh config string (or a new RoughEase instance) per tween rather than reusing one named ease.
