FrontendCanvasPerformanceMotion

How we redesigned Intervolutions: a cinematic hero drawn in Canvas

DN Dave Nebot · July 11, 2026 · 9 min read

Our own site had the classic cobbler's-children problem: it worked, but it didn't tell anyone who we are. We rebuilt it from scratch. This is the diary of how we put together the hero (the hardest part, and the most memorable) without dying on the performance front.

The starting point

We were coming from a background with green gradients and some connected constellation-style particles. It was fine, but generic: you've seen it in a thousand templates. We wanted something that said engineering + creativity at first glance: depth, slow and sophisticated motion, and an editorial, almost movie-trailer edge.

We set three rules before touching a line of code: dark and clean (midnight navy, not flat black), cobalt and cyan as the brand colors, and ambient motion that lifts the headline instead of competing with it.

Five layers, each with its own tool

The key to a background like this is not cramming everything into one place. We split it into layers and gave each one the tech that performs best: base gradient and vignette in pure CSS (zero cost), ambient glows as radial-gradient, and, most important, the orbital rings and particles in a single <canvas>.

The key decision

Reserve the Canvas for the one thing that truly benefits (dozens of moving dots and arcs) and leave the rest in static CSS. A DOM full of blur-animated divs would have been unmanageable.

Text that decodes itself

The tagline is «From zero to hero.». We added a scramble effect: on load, «hero» and the whole subtitle decode from random characters to the final text, like a terminal. The important detail is that we made it framerate-independent: each character has its own window in milliseconds, so the decode always takes ~0.9s even on a slow machine.

// cada carácter resuelve por tiempo, no por frames
const start = Math.random() * 420;               // ms
const end = start + 160 + Math.random() * 460;   // termina ~580–1040 ms
queue.push({ from: old[i] || '', to: newText[i] || '', start, end });

The war for 60 fps

This is where the project got interesting. The first version ran at 5 fps. Five. We measured layer by layer and found the culprits: mix-blend-mode and filter: blur() on large elements. Every frame, the compositor had to redo the blur of the entire screen because something (the canvas) was changing underneath.

5→60
fps after optimization
0
mix-blend-mode / blur at runtime
1
requestAnimationFrame loop

The fixes: switch the glows from filter: blur to radial-gradient (one paint, not a filter that re-rasterizes), remove all the mix-blend-mode, and move the rings from CSS (which rotated a conic mask and produced a subtle jitter) to Canvas, where they redraw cleanly on every frame.

90% of the performance of an animated background isn't in your algorithm: it's in not forcing the compositor to redo expensive layers every frame.

Mental note, commit at 2 a.m.

The result

A hero that shows from the very first pixel (the background slides under the transparent header, seamlessly), with a light that turns slowly around the headline, drifting particles, and the text decoding. And it respects prefers-reduced-motion: if you've asked for less motion, it freezes on a perfectly legible static frame.

What we took away

Performance and beauty aren't at odds, but they do fight. The version that's both pretty AND fast came from measuring instead of assuming: profiling each layer saved us hours of blind tweaking.

DN
Dave Nebot
The Intervolutions team · writes about what we build.

Shall we build something big? Put it together in 30 seconds.

Pick what you want to build and add powers: your plan takes shape in real time. No emails, no waiting. Play.

01 What are we building?
02 Add powers

Ballpark ranges based on +100 real projects. The real quote comes after a 20-minute call, and always with no fine print.

Your plan
Solid product
To sell for real from day one.
01 Development 02 Consulting 03 Cloud
Estimated time
69 weeks
Ballpark range
$4.99.7K
The whole team, no middlemen

Reply in 24–48h · Detailed proposal · No commitment

+100 projects delivered Reply within 24–48h Zero fluff