# Implementing Custom Interpolation in Remotion: A Complete Guide to Animation Primitives

> Learn to implement custom interpolation in Remotion using TypeScript. Animate numbers, colors, and styles with essential animation primitives for dynamic video creation.

- Repository: [Remotion/remotion](https://github.com/remotion-dev/remotion)
- Tags: how-to-guide
- Published: 2026-02-16

---

**Remotion provides a composable interpolation system through pure TypeScript functions like `interpolate`, `interpolateColors`, and `interpolateStyles`, allowing you to animate numbers, colors, CSS properties, and SVG paths by mapping input ranges to output ranges with optional easing.**

Remotion’s animation engine is built around a small set of low-level interpolation utilities that let you map any numeric input to any output type. These utilities are pure TypeScript functions located in the `remotion-dev/remotion` repository, so they can be composed, customized, and reused inside your own components to create smooth video animations.

## Understanding the Core `interpolate` Function

The foundation of Remotion’s animation system is the `interpolate` function defined in [`packages/core/src/interpolate.ts`](https://github.com/remotion-dev/remotion/blob/main/packages/core/src/interpolate.ts). This primitive accepts a numeric input, maps it from an input range to an output range, and returns the interpolated value.

```typescript
export function interpolate(
  input: number,
  inputRange: readonly number[],
  outputRange: readonly number[],
  options?: InterpolateOptions,
): number

```

### Range Validation and Extrapolation

According to the source code in [`packages/core/src/interpolate.ts`](https://github.com/remotion-dev/remotion/blob/main/packages/core/src/interpolate.ts), the function first validates that `inputRange` and `outputRange` have identical lengths and that all elements are finite numbers in monotonic order. For values falling outside the defined range, Remotion supports four **extrapolation types** via the `ExtrapolateType` union: `extend`, `identity`, `clamp`, and `wrap`. These determine whether the animation continues linearly, freezes at the boundary, or wraps around.

### Easing and Linear Interpolation

The `options` parameter accepts an optional **easing function** that transforms the linear progress into curved motion. If no easing is provided, the function performs standard linear interpolation by finding the containing segment via `findRange` and calculating the proportional distance between the two surrounding points.

## Built-in Interpolation Helpers

While the core `interpolate` function handles numbers, Remotion provides higher-level helpers that delegate to this primitive while managing complex data types like colors, CSS styles, and SVG paths.

### Color Interpolation with `interpolateColors`

The `interpolateColors` function in [`packages/core/src/interpolate-colors.ts`](https://github.com/remotion-dev/remotion/blob/main/packages/core/src/interpolate-colors.ts) enables smooth transitions between CSS color strings.

```typescript
export const interpolateColors = (
  input: number,
  inputRange: readonly number[],
  outputRange: readonly string[],
): string

```

Internally, the function parses CSS color strings into 32-bit ARGB numbers using `processColor`, splits the result into individual RGBA channels, interpolates each channel using the core `interpolate` function, and reassembles the output into a standard `rgba(r,g,b,a)` string.

### Style Object Interpolation with `interpolateStyles`

For animating complex CSS properties, `interpolateStyles` in [`packages/animation-utils/src/transformation-helpers/interpolate-styles/index.tsx`](https://github.com/remotion-dev/remotion/blob/main/packages/animation-utils/src/transformation-helpers/interpolate-styles/index.tsx) decomposes style objects into interpolatable parts.

```typescript
export const interpolateStyles = (
  input: number,
  inputRange: number[],
  outputStylesRange: Style[],
  options?: InterpolateOptions,
) => Style

```

The helper uses `breakDownValueIntoUnitNumberAndFunctions` to recursively decompose each CSS value into numbers, units, functions, or colors. The `interpolatedPropertyPart` function then handles four specific scenarios: forwarding colors to `interpolateColors`, recursively interpolating function arguments (like `translate(10px, 5px)`), blending unit-numbers while preserving units, and handling pure units when the numeric value is zero. The function validates structural compatibility between start and end values, throwing descriptive errors for mismatched shapes or non-animatable values before assembling the final style object.

### SVG Path Morphing with `interpolatePath`

For vector animations, `interpolatePath` in [`packages/paths/src/interpolate-path/interpolate-path.ts`](https://github.com/remotion-dev/remotion/blob/main/packages/paths/src/interpolate-path/interpolate-path.ts) enables frame-by-frame morphing between SVG path strings.

```typescript
export const interpolatePath = (
  value: number,
  firstPath: string,
  secondPath: string,
) => string

```

The implementation parses both SVG strings into command lists using `parsePath`, normalizes the lists via `reduceInstructions` to ensure identical lengths and compatible segment types, interpolates each command’s numeric parameters using the core `interpolate` function, and serializes the result back to a path string with `serializeInstructions`.

## Creating Custom Interpolation Functions

To extend Remotion’s animation system for custom data types or specialized CSS properties, you can compose the existing primitives. The general pattern involves parsing inputs into deterministic numeric structures, applying the core `interpolate` function with optional custom easing, and reassembling the result into the target format.

For example, to interpolate between CSS lengths that mix percentages and pixels, you can normalize both values to a common unit before interpolation:

```typescript
import {interpolate} from '@remotion/remotion';

/**
 * Interpolates a CSS length expressed either as a number (px) or a string ending with '%'.
 * The function treats percentages as fractions of a given base width.
 */
function interpolateLength(
  input: number,
  inputRange: [number, number],
  outputRange: [string | number, string | number],
  baseWidth: number,
  options?: InterpolateOptions,
) {
  // Convert both end values to pixels
  const toPx = (v: string | number) =>
    typeof v === 'number'
      ? v
      : parseFloat(v) / 100 * baseWidth; // % → px

  const pixelRange: [number, number] = [
    toPx(outputRange[0]),
    toPx(outputRange[1]),
  ];

  const px = interpolate(input, inputRange, pixelRange, options);
  return `${px}px`;
}

// Example – animate from 10% to 200px over a 400‑pixel container:
const width = interpolateLength(0.5, [0, 1], ['10%', 200], 400); // '210px'

```

This approach leverages the validation, easing, and extrapolation logic built into [`packages/core/src/interpolate.ts`](https://github.com/remotion-dev/remotion/blob/main/packages/core/src/interpolate.ts) while handling the domain-specific conversion between percentage strings and pixel values.

## Summary

- **Core primitive**: The `interpolate` function in [`packages/core/src/interpolate.ts`](https://github.com/remotion-dev/remotion/blob/main/packages/core/src/interpolate.ts) handles numeric mapping with support for easing, extrapolation, and range validation.
- **Color support**: `interpolateColors` in [`packages/core/src/interpolate-colors.ts`](https://github.com/remotion-dev/remotion/blob/main/packages/core/src/interpolate-colors.ts) parses CSS colors into RGBA channels and delegates to the core interpolator.
- **Style objects**: `interpolateStyles` in [`packages/animation-utils/src/transformation-helpers/interpolate-styles/index.tsx`](https://github.com/remotion-dev/remotion/blob/main/packages/animation-utils/src/transformation-helpers/interpolate-styles/index.tsx) recursively decomposes CSS values to animate complex properties like `transform` and `border`.
- **SVG paths**: `interpolatePath` in [`packages/paths/src/interpolate-path/interpolate-path.ts`](https://github.com/remotion-dev/remotion/blob/main/packages/paths/src/interpolate-path/interpolate-path.ts) normalizes and morphs between vector path strings.
- **Extensibility**: You can build custom interpolators by normalizing inputs to numbers, applying the core `interpolate` function, and reconstructing the output format.

## Frequently Asked Questions

### How do I implement easing in custom interpolation functions?

When building a custom interpolator, pass your easing function directly to the `options` parameter of the core `interpolate` function. The easing curve is applied to the normalized progress value (0 to 1) before the final numeric calculation, allowing you to reuse Remotion’s built-in easing curves like `Easing.elasticOut` or provide your own cubic-bezier function.

### Can I interpolate between custom data types not supported by Remotion?

Yes. To interpolate between custom data types—such as complex coordinate objects or domain-specific units—decompose the values into numeric components that the core `interpolate` function can process. After interpolation, reconstruct the data type from the resulting numbers. This pattern mirrors how `interpolateStyles` handles CSS functions and how `interpolatePath` handles SVG commands.

### What is the performance impact of using interpolateStyles versus manual interpolation?

`interpolateStyles` incurs a small overhead due to its recursive value decomposition and structural validation, which ensures type safety and prevents animation errors. For high-frequency animations (60 FPS video frames), this cost is negligible in most cases, but if you are animating thousands of elements per frame, you may see better performance by using the raw `interpolate` function on pre-extracted numeric values rather than full style objects.

### How does Remotion handle extrapolation when values fall outside the input range?

The core `interpolate` function accepts an `extrapolate` option in its configuration object that supports four behaviors: `extend` continues the interpolation linearly beyond the range, `clamp` freezes the value at the nearest boundary, `identity` returns the input value unchanged, and `wrap` cycles the value through the range. These options are defined in [`packages/core/src/interpolate.ts`](https://github.com/remotion-dev/remotion/blob/main/packages/core/src/interpolate.ts) and apply to all higher-level helpers that delegate to the core function.