A 3D scene on a website is always a trade-off between the wow factor and milliseconds. But it is a manageable trade-off: with the right architecture a WebGL background costs a few kilobytes at startup and zero milliseconds of render blocking.
Here is how the scenes work across our projects — including this very site.
The canvas only lives near the viewport
Every scene is wrapped in an IntersectionObserver: the canvas mounts as the block approaches the screen and unmounts once the user has scrolled past. That frees up WebGL contexts (browsers cap them at around 16) and keeps memory under control.
Scenes that must be ready instantly mount right away, but outside the viewport their render loop simply stops: no frames are drawn and no battery is spent.
Frame budget and degradation
The rules we follow in every scene:
- We cap DPR at 1.5 — on a retina screen the difference is invisible, but there are half as many pixels.
- On phones we cut the particle count by a factor of 2–2.5.
- We skip post-processing: a glow is cheaper to build with additive blending.
- prefers-reduced-motion — a single static frame instead of animation.
- 3D loads as a separate chunk after interactivity — LCP never waits for it.
The result
A page with a full particle scene of 20,000 points still scores 90+ in PageSpeed and does not heat up the phone. WebGL is not the enemy of speed — as long as you treat it as background music rather than the lead actor.