PTENES
MODULE 2.4

🖼️ Image & Media

Nine templates that transform still images into dynamic sequences: staggered galleries, center-focus carousels, before-and-after comparisons, and much more. Choose the right pattern for the right context.

8
Topics
45
Minutes
Medium
Level
Practical
Type
image / src staticFile() interpolate / spring translate · scale · opacity clip-path · stagger delay gallery-grid carousel comparison masonry polaroid split-screen 9 templates · each one solves a different visual pattern
1

🗂️ Overview — when to use image templates

Image and media templates solve a very common problem: you have photos or static assets and need to bring them to life in a video. Choosing the right template depends on how many items you have, if you want focus on one element or an ensemble narrative, and whether the content is comparative or sequential.

🎯 Quick decision map

  • •Too many photos with equal weight → gallery-grid or masonry-gallery
  • •One featured photo at a time → image-carousel or image-zoom-reveal
  • •Before and after → image-comparison-slider
  • •Nostalgic aesthetic / frame → polaroid-frame or photo-stack
  • •Two subjects at once → split-screen
  • •Main content + context → picture-in-picture

💡 File tip

All templates use staticFile() from Remotion for referencing local assets. Put your images in public/ at the project root and use staticFile("foto.jpg") — Remotion resolves the path in both Studio and the final render.

9 templates
In this category
staticFile()
Local assets
spring/interp
Main hooks
stagger
Recurring pattern
2

📐 gallery-grid — 2×3 grid with stagger

O gallery-grid arranges up to six images in a 2×3 grid where each card enters with a progressively longer delay (stagger). The result is that "cascade reveal" effect that adds rhythm without requiring any manual keyframes.

⚙️ How stagger works

Each item gets a delay proportional to its index. The spring starts earlier for the first item and later for the last, creating an entrance wave.

  • •Item 0 starts at frame 0; item 5 starts at frame 25 (delay = index × 5).
  • •spring({ frame: Math.max(frame - delay, 0), fps }) — the trick of Math.max prevents negative frames.
  • •The spring responds with 0→1; multiply by scale or opacity freely.
Stagger by index gallery-grid.tsx
import { spring, useCurrentFrame, useVideoConfig } from "remotion";

// dentro do .map((item, i) => ...)
const delay = i * 5;
const s = spring({
  frame: Math.max(frame - delay, 0),
  fps,
  config: { damping: 12, stiffness: 100 },
});
const scale = 0.8 + s * 0.2;

✓ What to DO

  • ✓Use images with the same aspect ratio to keep the grid uniform.
  • ✓Adjust the delay per item to control the wave speed.
  • ✓Combine with captions that enter alongside each card.

✗ What NOT to do

  • ✗Set the delay too high (>10/item) — the last card may never appear in the video.
  • ✗Mix image aspect ratios without objectFit: "cover".
  • ✗Use more than 9 items without adjusting the grid layout.
File
gallery-grid.tsx
Hook
spring + stagger
Layout
2×3 grid
Usage
Portfolio · photos
3

🎠 image-carousel — horizontal slide with centered focus

O image-carousel features slides in a horizontal row where only the centered item is at scale 1.0 — adjacent items progressively shrink. The frame determines where we are in the cycle, creating a continuous, smooth transition.

💡 The secret to central focus

The position of each slide is calculated as offset = índice - progress. When offset = 0, the item is exactly in the center and reaches maximum scale. The function interpolate(|offset|, [0,1,2], [1,0.75,0.55]) applies the gradual reduction to neighboring items.

Positioning by offset image-carousel.tsx
const cycleLength = fps * 2;
const progress = (frame % (cycleLength * slides.length)) / cycleLength;

slides.map((slide, i) => {
  const offset = i - progress;
  const translateX = offset * 280;
  const scale = interpolate(
    Math.abs(offset), [0, 1, 2], [1, 0.75, 0.55],
    { extrapolateRight: "clamp" }
  );
});
1

Adjust the cycle speed

Change fps * 2 to fps * 3 for slower slides, or fps * 1 for faster scrolling. Each cycle corresponds to the time a slide stays in the center.

2

Control the spacing between slides

The value 280 in translateX = offset * 280 sets the distance between centers. Reduce it for more overlapping slides; increase it for more spaced-out slides.

3

Add z-index based on the offset

The center slide should sit above the side slides. Use zIndex: Math.round(10 - Math.abs(offset) * 3) for automatic stacking.

File
image-carousel.tsx
Hook
interpolate · %
Visual
Central focus
Usage
Products · slides
4

↔️ image-comparison-slider — before and after

O image-comparison-slider splits the screen vertically with a divider that moves over time, revealing the “after” image from bottom to top while the “before” image remains visible on the left. It’s the ideal template for showing edits, product transformations, or design comparisons.

🔀 Clip-path technique

The "after" image is overlaid with position: absolute and a clipPath that limits the visible area to a fraction of the total width. The frame controls this fraction via interpolate:

const clipWidth = interpolate(frame, [0, durationInFrames], [0, 100], { extrapolateRight: "clamp" });
// style da imagem "depois":
clipPath: `inset(0 ${100 - clipWidth}% 0 0)`

✓ What to DO

  • ✓Use images that are exactly the same size for perfect alignment.
  • ✓Add a vertical divider as a visual indicator.
  • ✓Combine with “Before” / “After” text that fades out during the reveal.

✗ What NOT to do

  • ✗Images with different aspect ratios — the clip is off-center.
  • ✗Reveal too quickly — it loses the impact of the comparison.
  • ✗Apply to subjective comparisons without textual context.
File
image-comparison-slider.tsx
Hook
interpolate
Technique
clipPath inset
Usage
Before/after
5

🔍 image-zoom-reveal — zoom-out with focus

O image-zoom-reveal starts with the image highly zoomed in and progressively pulls back to its normal scale, creating a cinematic "pull back" effect. It feels like revealing the context around the initial detail.

💡 Why start enlarged

Starting with a detail grabs attention immediately — the viewer doesn’t know what they’re looking at. The gradual pullback builds tension, and the reveal of the full object makes an impact. Use long durations (fps × 3 or more) to maximize the dramatic effect.

Smoothed zoom-out with spring image-zoom-reveal.tsx
const { fps, durationInFrames } = useVideoConfig();
const s = spring({ frame, fps, config: { damping: 20, stiffness: 30 } });
// começa em 2.5×, chega a 1.0×
const scale = interpolate(s, [0, 1], [2.5, 1.0]);
const opacity = interpolate(frame, [0, 15], [0, 1], { extrapolateRight: "clamp" });
File
image-zoom-reveal.tsx
Hook
spring + interpolate
Start
Scale 2.5×
Usage
Dramatic reveal
6

🃏 masonry-gallery — Pinterest-style with spring

O masonry-gallery distributes blocks of varying heights across three columns, mimicking a Pinterest-style layout. Each block has its own spring delay, creating a sequence of pop-ins that feels deep and organic.

🏗️ Three-column architecture

The blocks are grouped by column before rendering. Each column is a flex-direction: column with gap. The blocks have different percentage heights to create the characteristic irregular masonry look.

// Blocos com delay e altura variável por coluna
const blocks = [
  { col: 0, height: "45%", delay: 0  },
  { col: 1, height: "55%", delay: 3  },
  { col: 2, height: "40%", delay: 5  },
];

✓ What to DO

  • ✓Distribute blocks of very different heights across columns for an organic effect.
  • ✓Stagger the delays so each column feels independent.
  • ✓Use gradients instead of images for quick prototypes.

✗ What NOT to do

  • ✗Use the same height for every block—you lose the masonry effect.
  • ✗Set all delays to the same value — it looks like an ordinary grid.
  • ✗Exceeding 3 columns without adjusting the parent container.
File
masonry-gallery.tsx
Hook
spring per block
Layout
3 flex columns
Usage
Varied portfolio
7

📚 Complete Library — all 9 templates

Quick reference for all templates in this category. Each row includes the name, the file in templates/, a descriptive line and the main hook used.

TemplateFileMain hook
gallery-grid gallery-grid.tsx spring + stagger delay
image-carousel image-carousel.tsx interpolate · cycle offset %
image-comparison-slider image-comparison-slider.tsx interpolate · clipPath inset
image-zoom-reveal image-zoom-reveal.tsx spring · scale 2.5→1
masonry-gallery masonry-gallery.tsx spring per block · 3 columns
photo-stack photo-stack.tsx spring · rotate + translateY
picture-in-picture picture-in-picture.tsx spring · corner position
polaroid-frame polaroid-frame.tsx spring · drop-in rotate
split-screen split-screen.tsx interpolate · two translateX panels
Total
9 templates
Base
templates/
Hooks
spring · interpolate
Pattern
stagger delay

📌 Module summary

✓
Decision map — choose the template by the number of items and the type of narrative (set vs. highlight).
✓
gallery-grid — stagger with Math.max(frame - delay, 0) creates a wave of reveals without manual keyframes.
✓
image-carousel — offset = índice - progress positions each slide relative to the center.
✓
image-comparison-slider — clipPath: inset() progressively reveals the image "afterward".
✓
masonry-gallery — blocks of varying heights in 3 columns with independent springs.
✓
staticFile() — always use this to reference local assets instead of absolute paths.

Next module:

2.5 — Backgrounds: nine animated background templates to set the context for any scene.