tappy@lab ~ % prism --guide
WebGL vs Canvas 2D for website backgrounds
WebGL shades every pixel on the GPU, so full-screen backgrounds stay cheap. Canvas 2D draws on the CPU, so its cost scales with how many objects you draw. Here is how to choose, with the numbers behind both.
Short answer
Use WebGL for full-screen backgrounds and Canvas 2D for anything that needs per-object motion. WebGL runs a fragment shader on the GPU, so a 1920x1080 background costs about the same as a 400x300 one. Canvas 2D draws on the CPU, so its cost scales with how many things you draw: 1,000 particles are cheap, 1,000,000 are not. TappyPrism ships both — 60 WebGL and 27 Canvas 2D effects — as single HTML files with no dependencies.
Side-by-side comparison
| WebGL | Canvas 2D | |
|---|---|---|
| Where it runs | GPU, through a fragment shader | CPU, through the 2D rasteriser |
| Cost scales with | Pixels x shader steps | Number of objects drawn per frame |
| Full-screen background | Ideal — a single draw call | Fine up to a few thousand elements |
| Browser support | All modern browsers | Everything, including very old hardware |
| Good at | Gradients, glow, distortion, caustics, light | Particles, trails, springs, procedural drawing |
| Crisp text and lines | Not its job — backgrounds only | Yes, vector-sharp at any DPR |
| Battery on mobile | Cheap per pixel, but a heavy shader still burns GPU | Cheap until the object count climbs |
| Examples in this library | Event Horizon, Silk Cascade, Gilded Fracture | Flow Field, Kinetic Grid, Strange Attractor |
How to choose
- The effect covers the whole viewport — gradients, glow, light, distortion: pick WebGL. One draw call, main thread stays free.
- You need to count or move discrete things — particles, nodes in a mesh, a pendulum: pick Canvas 2D, and keep the count in the low thousands.
- You must support old hardware or very low-power devices: pick Canvas 2D with fewer objects, or a WebGL shader that renders below native resolution.
- You are unsure: start from a WebGL effect, measure with the performance panel, and fall back to Canvas 2D if the GPU is the bottleneck.
Performance notes that apply to both
- Cap devicePixelRatio at 2. Rendering a 3x phone screen costs more than twice a 2x one for no visible gain.
- Pause when off-screen or when the tab is hidden. Every effect here does this with IntersectionObserver and a visibility check.
- Honour prefers-reduced-motion, and do not autoplay heavy motion on phones.
- Render expensive shaders at a fraction of native resolution. Silk Cascade renders at 1x CSS pixels on purpose and looks the same.
- Expose one constant for density — particle count, grid resolution — so you can tune per device without rewriting the effect.
Frequently asked questions
Which is faster for a full-screen background?
WebGL. A fragment shader runs once per pixel on the GPU, so the cost is roughly constant no matter how complex the pattern is, while Canvas 2D has to push every pixel from the CPU. For a background that covers the whole viewport, WebGL is usually the cheaper option and leaves the main thread free.
Does WebGL drain more battery on phones?
It depends on the shader, not on the API. A simple gradient shader is cheaper than a Canvas 2D scene with 2,000 animated particles, because the GPU does less work per frame. A shader that steps each ray dozens of times — like a raymarched black hole — will warm a phone. If you are targeting low-power devices, prefer a light shader or a Canvas 2D effect with fewer objects.
Do I need three.js or another library?
No. Every effect here is raw WebGL or raw Canvas 2D in a single HTML file with no dependencies. The WebGL effects compile a vertex and fragment shader directly, which is all you need for a background. Reach for three.js when you need 3D scenes, cameras and geometry, not for a shader background.
Can I use both on the same page?
Yes, and it is often the right answer: run a WebGL shader as the base background and layer a small Canvas 2D canvas on top for particles or UI-adjacent motion. Two canvases cost one GPU context and one 2D context, which every modern browser handles fine.
How do I keep a shader background fast?
Cap devicePixelRatio at 2, pause the animation when it scrolls off-screen or the tab is hidden, and render expensive shaders at a fraction of native resolution — soft imagery survives upscaling almost unchanged. Every effect in this library already caps DPR and pauses when off-screen.