Easing

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

Mechanics

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.

rough-ease.js
  • 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 (default none) - out, in, or both to fade the roughness toward that end so the value can settle instead of shaking right up to the finish.
  • randomize (default true) - shuffles the order of the point magnitudes. Set false and the deviations decrease steadily instead of scattering.
  • clamp (default false) - set true to 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.out to shake while decelerating.

This is exactly the motion people disable

A jittering ease is the kind of thing 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.
When

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
Alternatives

Use something else when

  • You want a clean, responsive landing - use expo.out or power4.out, not noise
  • You want a single controlled overshoot - use back.out(1.7) or elastic.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/y keyframes on a separate tween and leave the main ease alone
In production

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

Keep durations short. A rough tween at 0.8s already fits a lot of jitter in, and at 2s the noise reads as broken rather than intentional. If it looks like too much, drop points before you touch strength.
Used in components

See it running in production

FAQ

Common questions

What's the difference between strength and points in rough()?
strength controls how far the value deviates from the straight line (the amplitude of the jitter), points controls 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' then gsap.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 reason ease: 'rough(...)' silently falls back to linear.
How do I stop rough from overshooting past the end value?
Add clamp: true to 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: true keeps 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 a template ease like power2.out if 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: true only 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.