bygreensock· 8 skills
Official GSAP skill for gsap.utils — clamp, mapRange, normalize, interpolate, random, snap, toArray, wrap, pipe. Use when the user asks about gsap.utils, clamp, mapRange, random, snap, toArray, wrap, or helper utilities in GSAP.
$npx -y skills add greensock/gsap-skills --skill gsap-utilsInstalls into the current project.
Run `npx skills use "https://github.com/greensock/gsap-skills" --skill "greensock/gsap-skills/gsap-utils"` and follow the generated skill instructions now. Read its complete output, redirecting it to a temporary file first if necessary. Resolve relative paths from the supporting-files directory it provides.
Use the skills in "https://github.com/greensock/gsap-skills" that are relevant to the current task. Run `npx skills add "https://github.com/greensock/gsap-skills"` and select the relevant skills, then follow their instructions.
| 1 | # gsap.utils |
| 2 | |
| 3 | ## When to Use This Skill |
| 4 | |
| 5 | Apply when writing or reviewing code that uses **gsap.utils** for math, array/collection handling, unit parsing, or value mapping in animations (e.g. mapping scroll to a value, randomizing, snapping to a grid, or normalizing inputs). |
| 6 | |
| 7 | **Related skills:** Use with **gsap-core**, **gsap-timeline**, and **gsap-scrolltrigger** when building animations; CustomEase and other easing utilities are in **gsap-plugins**. |
| 8 | |
| 9 | ## Overview |
| 10 | |
| 11 | **gsap.utils** provides pure helpers; no need to register. Use in tween vars (e.g. function-based values), in ScrollTrigger or Observer callbacks, or in any JS that drives GSAP. All are on **gsap.utils** (e.g. `gsap.utils.clamp()`). |
| 12 | |
| 13 | **Omitting the value: function form.** Many utils accept the value to transform as the **last** argument. If you omit that argument, the util returns a **function** that accepts the value later. Use the function form when you need to clamp, map, normalize, or snap many values with the same config (e.g. in a mousemove handler or tween callback). **Exception: random()** — pass **true** as the last argument to get a reusable function (do not omit the value); see [random()](https://gsap.com/docs/v3/GSAP/UtilityMethods/random()). |
| 14 | |
| 15 | ```javascript |
| 16 | // With value: returns the result |
| 17 | gsap.utils.clamp(0, 100, 150); // 100 |
| 18 | |
| 19 | // Without value: returns a function you call with the value later |
| 20 | let c = gsap.utils.clamp(0, 100); |
| 21 | c(150); // 100 |
| 22 | c(-10); // 0 |
| 23 | ``` |
| 24 | |
| 25 | ## Clamping and Ranges |
| 26 | |
| 27 | ### clamp(min, max, value?) |
| 28 | |
| 29 | Constrains a value between min and max. Omit **value** to get a function: `clamp(min, max)(value)`. |
| 30 | |
| 31 | ```javascript |
| 32 | gsap.utils.clamp(0, 100, 150); // 100 |
| 33 | gsap.utils.clamp(0, 100, -10); // 0 |
| 34 | |
| 35 | let clampFn = gsap.utils.clamp(0, 100); |
| 36 | clampFn(150); // 100 |
| 37 | ``` |
| 38 | |
| 39 | ### mapRange(inMin, inMax, outMin, outMax, value?) |
| 40 | |
| 41 | Maps a value from one range to another. Use when converting scroll position, progress (0–1), or input range to an animation range. Omit **value** to get a function: `mapRange(inMin, inMax, outMin, outMax)(value)`. |
| 42 | |
| 43 | ```javascript |
| 44 | gsap.utils.mapRange(0, 100, 0, 500, 50); // 250 |
| 45 | gsap.utils.mapRange(0, 1, 0, 360, 0.5); // 180 (progress to degrees) |
| 46 | |
| 47 | let mapFn = gsap.utils.mapRange(0, 100, 0, 500); |
| 48 | mapFn(50); // 250 |
| 49 | ``` |
| 50 | |
| 51 | ### normalize(min, max, value?) |
| 52 | |
| 53 | Returns a value normalized to 0–1 for the given range. Inverse of mapping when the target range is 0–1. Omit **value** to get a function: `normalize(min, max)(value)`. |
| 54 | |
| 55 | ```javascript |
| 56 | gsap.utils.normalize(0, 100, 50); // 0.5 |
| 57 | gsap.utils.normalize(100, 300, 200); // 0.5 |
| 58 | |
| 59 | let normFn = gsap.utils.normalize(0, 100); |
| 60 | normFn(50); // 0.5 |
| 61 | ``` |
| 62 | |
| 63 | ### interpolate(start, end, progress?) |
| 64 | |
| 65 | Interpolates between two values at a given progress (0–1). Handles numbers, colors, and objects with matching keys. Omit **progress** to get a function: `interpolate(start, end)(progress)`. |
| 66 | |
| 67 | ```javascript |
| 68 | gsap.utils.interpolate(0, 100, 0.5); // 50 |
| 69 | gsap.utils.interpolate("#ff0000", "#0000ff", 0.5); // mid color |
| 70 | gsap.utils.interpolate({ x: 0, y: 0 }, { x: 100, y: 50 }, 0.5); // { x: 50, y: 25 } |
| 71 | |
| 72 | let lerp = gsap.utils.interpolate(0, 100); |
| 73 | lerp(0.5); // 50 |
| 74 | ``` |
| 75 | |
| 76 | ## Random and Snap |
| 77 | |
| 78 | ### random(minimum, maximum[, snapIncrement, returnFunction]) / random(array[, returnFunction]) |
| 79 | |
| 80 | Returns a random number in the range **minimum**–**maximum**, or a random element from an **array**. Optional **snapIncrement** snaps the result to the nearest multiple (e.g. `5` → multiples of 5). **To get a reusable function**, pass **true** as the last argument (**returnFunction**); the returned function takes no args and returns a new random value each time. This is the only util that uses `true` for the function form instead of omitting the value. |
| 81 | |
| 82 | ```javascript |
| 83 | // immediate value: number in range |
| 84 | gsap.utils.random(-100, 100); // e.g. 42.7 |
| 85 | gsap.utils.random(0, 500, 5); // 0–500, snapped to nearest 5 |
| 86 | |
| 87 | // reusable function: pass true as last argument |
| 88 | let randomFn = gsap.utils.random(-200, 500, 10, true); |
| 89 | randomFn(); // random value in range, snapped to 10 |
| 90 | randomFn(); // another random value |
| 91 | |
| 92 | // array: pick one value at random |
| 93 | gsap.utils.random(["red", "blue", "green"]); // "red", "blue", or "green" |
| 94 | let randomFromArray = gsap.utils.random([0, 100, 200], true); |
| 95 | randomFromArray(); // 0, 100, or 200 |
| 96 | ``` |
| 97 | |
| 98 | **String form in tween vars:** use `"random(-100, 100)"`, `"random(-100, 100, 5)"`, or `"random([0, 100, 200])"`; GSAP evaluates it per target. |
| 99 | |
| 100 | ```javascript |
| 101 | gsap.to(".box", { x: "random(-100, 100, 5)", duration: 1 }); |
| 102 | gsap.to(".item", { backgroundColor: "random([red, blue, green])" }); |
| 103 | ``` |
| 104 | |
| 105 | ### snap(snapTo, value?) |
| 106 | |
| 107 | Snaps a value to the nearest multiple of **snapTo**, or to the nearest value in an array of allowed values. Omit **value** to get a function: `snap(snapTo)(value)` (or `snap(snapArray)(value)`). |
| 108 | |
| 109 | ```javascript |
| 110 | gsap.utils.snap(10, 23); // 20 |
| 111 | gsap.utils.snap(0.25, 0.7); // 0.75 |
| 112 | gsap.utils.snap([0, 100, 200], 150); // 100 or 200 (nearest in array) |
| 113 | |
| 114 | let snapFn = gsap.utils.snap(10); |
| 115 | snapFn(23); // 20 |
| 116 | ``` |
| 117 | |
| 118 | Use in tweens for grid or step-based animation: |
| 119 | |
| 120 | ```javascript |
| 121 | gsap.to(".x", { x: 200, snap: { x: 20 } }); |
| 122 | ``` |
| 123 | |
| 124 | ### shuffle(array) |
| 125 | |
| 126 | Returns a new array with the same elements in random order. Use for randomizing order (e.g. stagger from "random" with a copy). |
| 127 | |
| 128 | ```javascript |
| 129 | gsap.utils.shuffle([1, 2, 3, 4]); // e.g. [3, 1, 4, 2] |
| 130 | ``` |
| 131 | |
| 132 | ### distribute(config) |
| 133 | |
| 134 | **Returns a function** that assigns a value to each target based on its position in the array (or in a grid). Used internally for advanced staggers; use it whenever you need values spread across many elements (e.g. scale, opacity, x, delay). The returned function receives `(index, target, targets)` — either call it manually or pass the result directly into a tween; GSAP will call it per target with index, element, and array. |
| 135 | |
| 136 | **Config (all optional):** |
| 137 | |
| 138 | | Property | Type | Description | |
| 139 | |----------|------|-------------| |
| 140 | | `base` | Number | Starting value. Default `0`. | |
| 141 | | `amount` | Number | Total to distribute across all targets (added to base). E.g. `amount: 1` with 100 targets → 0.01 between each. Use **each** instead to set a fixed step per target. | |
| 142 | | `each` | Number | Amount to add between each target (added to base). E.g. `each: 1` with 4 targets → 0, 1, 2, 3. Use **amount** instead to split a total. | |
| 143 | | `from` | Number \| String \| Array | Where distribution starts: index, or `"start"`, `"center"`, `"edges"`, `"random"`, `"end"`, or ratios like `[0.25, 0.75]`. Default `0`. | |
| 144 | | `grid` | String \| Array | Use grid position instead of flat index: `[rows, columns]` (e.g. `[5, 10]`) or `"auto"` to detect. Omit for flat array. | |
| 145 | | `axis` | String | For grid: limit to one axis (`"x"` or `"y"`). | |
| 146 | | `ease` | Ease | Distribute values along an ease curve (e.g. `"power1.inOut"`). Default `"none"`. | |
| 147 | |
| 148 | **In a tween:** pass the result of `distribute(config)` as the property value; GSAP calls the function for each target with `(index, target, targets)`. |
| 149 | |
| 150 | ```javascript |
| 151 | // Scale: middle elements 0.5, outer edges 3 (amount 2.5 distributed from center) |
| 152 | gsap.to(".class", { |
| 153 | scale: gsap.utils.distribute({ |
| 154 | base: 0.5, |
| 155 | amount: 2.5, |
| 156 | from: "center" |
| 157 | }) |
| 158 | }); |
| 159 | ``` |
| 160 | |
| 161 | **Manual use:** call the returned function with `(index, target, targets)` to get the value for that index. |
| 162 | |
| 163 | ```javascript |
| 164 | const distributor = gsap.utils.distribute({ |
| 165 | base: 50, |
| 166 | amount: 100, |
| 167 | from: "center", |
| 168 | ease: "power1.inOut" |
| 169 | }); |
| 170 | const targets = gsap.utils.toArray(".box"); |
| 171 | const valueForIndex2 = distributor(2, targets[2], targets); |
| 172 | ``` |
| 173 | |
| 174 | See [distribute()](https://gsap.com/docs/v3/GSAP/UtilityMethods/distribute/) for more. |
| 175 | |
| 176 | ## Units and Parsing |
| 177 | |
| 178 | ### getUnit(value) |
| 179 | |
| 180 | Returns the unit string of a value (e.g. `"px"`, `"%"`, `"deg"`). Use when normalizing or converting values. |
| 181 | |
| 182 | ```javascript |
| 183 | gsap.utils.getUnit("100px"); // "px" |
| 184 | gsap.utils.getUnit("50%"); // "%" |
| 185 | gsap.utils.getUnit(42); // "" (unitless) |
| 186 | ``` |
| 187 | |
| 188 | ### unitize(value, unit) |
| 189 | |
| 190 | Appends a unit to a number, or returns the value as-is if it already has a unit. Use when building CSS values or tween end values. |
| 191 | |
| 192 | ```javascript |
| 193 | gsap.utils.unitize(100, "px"); // "100px" |
| 194 | gsap.utils.unitize("2rem", "px"); // "2rem" (unchanged) |
| 195 | ``` |
| 196 | |
| 197 | ### splitColor(color, returnHSL?) |
| 198 | |
| 199 | Converts a color string into an array: **[red, green, blue]** (0–255), or **[red, green, blue, alpha]** (4 elements for RGBA when alpha is present or required). Pass **true** as the second argument (**returnHSL**) to get **[hue, saturation, lightness]** or **[hue, saturation, lightness, alpha]** (HSL/HSLA) instead. Works with `"rgb()"`, `"rgba()"`, `"hsl()"`, `"hsla()"`, hex, and named colors (e.g. `"red"`). Use when animating color components or building gradients. See [splitColor()](https://gsap.com/docs/v3/GSAP/UtilityMethods/splitColor/). |
| 200 | |
| 201 | ```javascript |
| 202 | gsap.utils.splitColor("red"); // [255, 0, 0] |
| 203 | gsap.utils.splitColor("#6fb936"); // [111, 185, 54] |
| 204 | gsap.utils.splitColor("rgba(204, 153, 51, 0.5)"); // [204, 153, 51, 0.5] (4 elements) |
| 205 | gsap.utils.splitColor("#6fb936", true); // [94, 55, 47] (HSL: hue, saturation, lightness) |
| 206 | ``` |
| 207 | |
| 208 | ## Arrays and Collections |
| 209 | |
| 210 | ### selector(scope) |
| 211 | |
| 212 | Returns a scoped selector function that finds elements only within the given element (or ref). Use in components so selectors like `".box"` match only descendants of that component, not the whole document. Accepts a DOM element or a ref (e.g. React ref; handles `.current`). |
| 213 | |
| 214 | ```javascript |
| 215 | const q = gsap.utils.selector(containerRef); |
| 216 | q(".box"); // array of .box elements inside container |
| 217 | gsap.to(q(".circle"), { x: 100 }); |
| 218 | ``` |
| 219 | |
| 220 | ### toArray(value, scope?) |
| 221 | |
| 222 | Converts a value to an array: selector string (scoped to element), NodeList, HTMLCollection, single element, or array. Use when passing mixed inputs to GSAP (e.g. targets) and a true array is needed. |
| 223 | |
| 224 | ```javascript |
| 225 | gsap.utils.toArray(".item"); // array of elements |
| 226 | gsap.utils.toArray(".item", container); // scoped to container |
| 227 | gsap.utils.toArray(nodeList); // [ ... ] from NodeList |
| 228 | ``` |
| 229 | |
| 230 | ### pipe(...functions) |
| 231 | |
| 232 | Composes functions: **pipe(f1, f2, f3)(value)** returns f3(f2(f1(value))). Use when applying a chain of transforms (e.g. normalize → mapRange → snap) in a tween or callback. |
| 233 | |
| 234 | ```javascript |
| 235 | const fn = gsap.utils.pipe( |
| 236 | (v) => gsap.utils.normalize(0, 100, v), |
| 237 | (v) => gsap.utils.snap(0.1, v) |
| 238 | ); |
| 239 | fn(50); // normalized then snapped |
| 240 | ``` |
| 241 | |
| 242 | ### wrap(min, max, value?) |
| 243 | |
| 244 | Wraps a value into the range min–max (inclusive min, exclusive max). Use for infinite scroll or cyclic values. Omit **value** to get a function: `wrap(min, max)(value)`. |
| 245 | |
| 246 | ```javascript |
| 247 | gsap.utils.wrap(0, 360, 370); // 10 |
| 248 | gsap.utils.wrap(0, 360, -10); // 350 |
| 249 | |
| 250 | let wrapFn = gsap.utils.wrap(0, 360); |
| 251 | wrapFn(370); // 10 |
| 252 | ``` |
| 253 | |
| 254 | ### wrapYoyo(min, max, value?) |
| 255 | |
| 256 | Wraps value in range with a yoyo (bounces at ends). Use for back-and-forth within a range. Omit **value** to get a function: `wrapYoyo(min, max)(value)`. |
| 257 | |
| 258 | ```javascript |
| 259 | gsap.utils.wrapYoyo(0, 100, 150); // 50 (bounces back) |
| 260 | |
| 261 | let wrapY = gsap.utils.wrapYoyo(0, 100); |
| 262 | wrapY(150); // 50 |
| 263 | ``` |
| 264 | |
| 265 | ## Best practices |
| 266 | |
| 267 | - ✅ Omit the value argument to get a reusable function when the same range/config is used many times (e.g. scroll handler, tween callback): `let mapFn = gsap.utils.mapRange(0, 1, 0, 360); mapFn(progress)`. |
| 268 | - ✅ Use **snap** for grid-aligned or step-based values; use **toArray** when GSAP or your code needs a real array from a selector or NodeList. |
| 269 | - ✅ Use **gsap.utils.selector(scope)** in components so selectors are scoped to a container or ref. |
| 270 | |
| 271 | ## Do Not |
| 272 | |
| 273 | - ❌ Assume **mapRange** / **normalize** handle units; they work on numbers. Use **getUnit** / **unitize** when units matter. |
| 274 | - ❌ Override or rely on undocumented behavior; stick to the documented API. |
| 275 | |
| 276 | ### Learn More |
| 277 | |
| 278 | https://gsap.com/docs/v3/HelperFunctions |