skill

Remotion Interactivity

Structure Remotion markup for interactivity

remotion-dev97,781+ installsVetted

About

By writing Remotion markup in a specific way, the Remotion Studio is able to recognize the structure of the code and makes it interactive:

- Allowing items to be selected by clicking on them - Allowing drag+drop, resizing and rotation - Editing the CSS styles - Making keyframes and easing values editable

If the markup is too complex for the Studio to make it interactive, then the values become grayed out.

## Make an HTML element interactive using `Interactive`

Every HTML and SVG element (except `<Img>`, it already is interactive) such as `<div>` can be turned interactive using `Interactive`:

```tsx title="Interactive elements" <Interactive.Div name="Greeting card" style={{fontSize: 80, padding: 24}} > Hello </Interactive.Div> ```

This allows styles and keyframes to be set in the Studio. Be sensible, if a component has many elements, the timeline might get messy.

## Prefer inline text

If text is fixed and only used once, write it directly inside the interactive element instead of extracting it into a constant.

```tsx title="Inline text" // 👍 Fixed copy stays editable <Interactive.Div name="Title"> Remotion Best Practices </Interactive.Div> ```

Use a prop or variable only when the text is dynamic or reused.

## Give interactive elements a descriptive name

Add a `name` prop to elements to make them easily identifyable. Avoid computed names, hardcode them.

```tsx title="Interactive names" <> <Interactive.Div name="Hero title" style={{fontSize: 80}}> Launch day </Interactive.Div> <Img name="Avatar" src="https://remotion.media/image.jpeg" /> <Video name="Background" src="https://remotion.media/video.mp4" /> <Sequence name="Title"> Launch day </Sequence> </> ```

## Keep all CSS styles inline

The best way is to just pass a plain object to `style` - no referring to constants, no object spreading, no math.

```tsx title="Interactive example" <Interactive.Div style={{ fontSize: 80, color: 'red', }} > Hello World! </Interactive.Div> ```

```tsx title="❌ Bad for interactivity" const baseStyle = useMemo(() => { return { fontSize: 12 // ❌ Non-inline styles are not supported } }, []);

<Interactive.Div style={{ ...baseStyle, // ❌ Spreading is not supported color: RED, // ❌ Referring to constants is not supported scale: frame * 10 // ❌ Math is not supported }} > Hello World! </Interactive.Div> ```

## Animate using `interpolate()`

Write animations as inline `interpolate()` calls on the property that changes. The output range, easing, extrapolation and `output` property should use hardcoded values.

The input range may additionally use `durationInFrames`, `fps`, `width` and `height` destructured directly from `useVideoConfig()`. Bare identifiers such as `durationInFrames`, multiplication with a number such as `2 * fps` or `fps * 2`, and subtraction of a number such as `durationInFrames - 1` are supported.

```tsx title="Inline values" const {fps, durationInFrames} = useVideoConfig();

// 👍 Inline values can be standardized and keyframed <Interactive.Div name="Product card" style={{ color: 'white', fontSize: 80, scale: interpolate(frame, [0, fps], [0, 1], { easing: Easing.spring({damping: 200}), output: 'perceptual-scale', extrapolateLeft: 'clamp', extrapolateRight: 'clamp' }), rotate: interpolate(frame, [0, 1 * fps], ['0deg', '20deg'], { easing: Easing.spring({damping: 200}), extrapolateLeft: 'clamp', extrapolateRight: 'clamp' }), translate: interpolate( frame, [durationInFrames - 30, durationInFrames], ['0px 0px', '0px 120px'], { easing: Easing.spring({damping: 200}), output: 'perceptual-scale', extrapolateLeft: 'clamp', extrapolateRight: 'clamp' } ), }} /> ```

```tsx title="❌ Bad interactivity" const translateY = interpolate(frame, [0, 30], [0, 120]); // ❌ Math should be directly in the markup

<Interactive.Div name="Product card" style={{ translate: translateY, // ❌ Only inline interpolate() calls are supported, rotate: interpolate(frame, [start, start + 10], [0, Math.PI]), // ❌ Cannot use math with arbitrary variables, cannot use constants scale: interpolate(anyVariable, [0, 30], [0, 1]) // ❌ Can only interpret the `frame` variable. }} /> ```

## Keep SVG paths editable with `Interactive.Path`

Use `<Interactive.Path>` from `remotion` instead of `<path>` inside an SVG to make the path visually editable.

Install `@remotion/paths` for path interpolation and Studio path keyframes:

```sh bunx remotion add @remotion/paths ```

If the geometry is meant to be static, put the path string directly in the `d` prop. Do not extract it into a constant.

```tsx title="Editable static path" import {Interactive} from 'remotion';

<Interactive.Svg width={300} height={300} viewBox="0 0 300 300"> <Interactive.Path name="Triangle" d="M 40 40 L 260 40 L 150 260 Z" fill="#0b84f3"

Install

Run this command

npx skills add remotion-dev/skills

Works with

claude appclaude codeclaude apicursorcodexwindsurfclinezed

Manual steps

Install with `npx skills add remotion-dev/skills`, or clone the repository and copy the `skills/remotion-interactivity` folder into your Claude skills directory.

View source

Frequently asked questions

What is the Remotion Interactivity skill?

Structure Remotion markup for interactivity

How do I install Remotion Interactivity?

Run this in your terminal:

npx skills add remotion-dev/skills
Which AI tools does Remotion Interactivity work with?

It works with claude_app, claude_code, claude_api, cursor, codex, windsurf, cline, zed.

Who made Remotion Interactivity?

remotion-dev.

Is Remotion Interactivity free?

Yes, it is free to use.

Related assets

More curated picks in Productivity & Office.

All Remotion Interactivity alternatives →

Audit before you install

Run any source through our checks - AI visibility, security, performance, and stack detection.

More in Productivity & Office