web2vid

Make a perfect, seamless loop

Build an HTML or canvas animation that loops without a visible seam, by making everything a function of time modulo the loop length, and render it frame-perfectly.

Updated 2026-10-30

A loop is seamless when the frame after the last one is exactly the first one again. With a normal screen recording that’s luck. With web2vid it’s maths, because the clock is exact.

The rule

Pick a loop length T and make everything in the animation a function of t % T:

const T = 6000; // ms

function frame(t) {
  const phase = (t % T) / T; // 0..1, exactly, on every frame
  draw(phase);
  requestAnimationFrame(frame);
}
requestAnimationFrame(frame);

Then render with a duration of exactly T (6 seconds here). The last frame is at 5.967 s, and the next one would be 6.000 s, which is 0 again: no seam.

Things that move at different speeds

Make each speed a whole number of cycles per loop:

If a speed doesn’t fit (2.5 cycles per loop), it will jump at the seam.

With CSS animations

Make the render duration a multiple of every animation’s duration. A 2 s @keyframes loop and a 3 s one both fit in a 6 s render. web2vid pauses and seeks CSS animations to the exact frame time, so they line up perfectly.

Random, but repeatable

Math.random() gives different values every run, and a loop can’t jump. Use a seeded function of something stable instead, for example an index:

const rnd = (n) => { const x = Math.sin(n * 127.1) * 43758.5453; return x - Math.floor(x); };

The hero animation on web2vid.com is built exactly like this.