Skip to main content

Overview

Create a MotionValue that transforms the output of another MotionValue by mapping it from one range of values into another, or by applying a custom function.

Import

import { useTransform } from "motion/react"

Signatures

Range Mapping

function useTransform<I, O>(
  value: MotionValue<number>,
  inputRange: number[],
  outputRange: O[],
  options?: TransformOptions<O>
): MotionValue<O>

Transform Function

function useTransform<I, O>(
  input: MotionValue<I>,
  transformer: (input: I) => O
): MotionValue<O>

Multiple Inputs

function useTransform<I, O>(
  input: MotionValue[],
  transformer: (inputs: I[]) => O
): MotionValue<O>

Multiple Outputs (Map)

function useTransform<T extends Record<string, any[]>>(
  inputValue: MotionValue<number>,
  inputRange: number[],
  outputMap: T,
  options?: TransformOptions<T[keyof T][number]>
): { [K in keyof T]: MotionValue<T[K][number]> }

Parameters

Range Mapping Parameters

value
MotionValue<number>
required
The input MotionValue to transform
inputRange
number[]
required
A linear series of numbers (either all increasing or decreasing)
outputRange
O[]
required
A series of values to map to. Must be the same length as inputRange. Can be numbers, colors, strings, or other animatable values
options
TransformOptions<O>
Optional transform configuration:
  • clamp: Clamp values to within the given range (default: true)
  • ease: Easing function(s) to apply between values
  • mixer: Custom interpolation function

Function Transform Parameters

input
MotionValue<I> or MotionValue[]
required
The input MotionValue(s) to transform
transformer
(input: I) => O
required
A function that accepts the latest value(s) and returns a new value

Usage

Basic Range Mapping

Map input values to output values:
import { motion, useMotionValue, useTransform } from "motion/react"

export function Component() {
  const x = useMotionValue(0)
  const opacity = useTransform(x, [-200, 0, 200], [0, 1, 0])

  return (
    <motion.div
      style={{ x, opacity }}
      drag="x"
    />
  )
}

Complex Range Mapping

Transform with multiple breakpoints:
import { motion, useMotionValue, useTransform } from "motion/react"

export function Component() {
  const x = useMotionValue(0)
  const xRange = [-200, -100, 100, 200]
  const opacityRange = [0, 1, 1, 0]
  const opacity = useTransform(x, xRange, opacityRange)

  return (
    <motion.div
      animate={{ x: 200 }}
      style={{ opacity, x }}
    />
  )
}

Transform Function

Apply custom transformation logic:
import { motion, useMotionValue, useTransform } from "motion/react"

export function Component() {
  const x = useMotionValue(10)
  const y = useTransform(x, (value) => value * 2)

  return <motion.div style={{ x, y }} />
}

Multiple Input Values

Combine multiple motion values:
import { motion, useMotionValue, useTransform } from "motion/react"

export function Component() {
  const x = useMotionValue(0)
  const y = useMotionValue(0)
  const z = useTransform([x, y], ([latestX, latestY]) => {
    return latestX * latestY
  })

  return <motion.div style={{ x, y, z }} />
}

Color Transformations

Transform between colors:
import { motion, useMotionValue, useTransform } from "motion/react"

export function Component() {
  const x = useMotionValue(0)
  const background = useTransform(
    x,
    [0, 100],
    ["#ff0000", "#0000ff"]
  )

  return <motion.div style={{ x, background }} drag="x" />
}

Multiple Outputs

Create multiple transformed values from a single input:
import { motion, useMotionValue, useTransform } from "motion/react"

export function Component() {
  const x = useMotionValue(0)
  const { opacity, scale } = useTransform(x, [0, 100], {
    opacity: [0, 1],
    scale: [0.5, 1]
  })

  return <motion.div style={{ opacity, scale, x }} />
}

With Easing

Apply easing functions to transformations:
import { motion, useMotionValue, useTransform } from "motion/react"

export function Component() {
  const x = useMotionValue(0)
  const opacity = useTransform(
    x,
    [0, 100],
    [0, 1],
    { ease: (t) => t * t } // quadratic easing
  )

  return <motion.div style={{ x, opacity }} />
}

Without Clamping

Allow values to extrapolate beyond ranges:
import { motion, useMotionValue, useTransform } from "motion/react"

export function Component() {
  const x = useMotionValue(0)
  const scale = useTransform(
    x,
    [0, 100],
    [1, 2],
    { clamp: false }
  )

  return <motion.div style={{ x, scale }} />
}

Notes

  • Transformed values automatically update when their dependencies change
  • The input range must be a linear series (all increasing or all decreasing)
  • All values in the output range must be the same type and format
  • By default, values are clamped to the output range
  • Easing functions apply between each pair of values in the ranges

Build docs developers (and LLMs) love