Skip to content
Free audit Get a quote
FrontendCanvasPerformanceMotion

How we redesigned Intervolutions: a cinematic hero drawn in Canvas

David Abellán · · 2 min read
How we redesigned Intervolutions: a cinematic hero drawn in Canvas

Our site did its job, but we wanted it to tell who we are. So we rebuilt it from scratch, with the same method we bring to a client project. This is the diary of how we put together the hero (the hardest part, and the most memorable) without giving up a frame of performance.

The starting point

We were coming from a background with green gradients and some connected constellation-style particles. It did the job, but it was not ours. 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.

// each character resolves by time, not by frames
const start = Math.random() * 420;               // ms
const end = start + 160 + Math.random() * 460;   // ends ~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 target was 60 fps with every layer on, and the way there was measuring layer by layer until we saw where the budget went: mix-blend-mode and filter: blur() on large elements. With those, the compositor has to redo the blur of the entire screen every frame because something (the canvas) changes underneath.

60
fps with every layer on
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.

Team note

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.

David Abellán
Co-founder · Engineering
Co-founder of Intervolutions. Architecture, code and infrastructure since 2010, with projects delivered in seven countries.
What we do about this when the project is yours

Share this

Link to this page: https://intervolutions.com/devlog/rediseno-intervolutions-hero-canvas/

What will your website cost?

Pick what you need, add extras if you want, and watch the price range and timeline update as you go. When it looks right, send it and we reply with a fixed price within one business day.