A Stripe-style WebGL gradient—without Three.js
Why WebGL at all?
A flat CSS gradient on a landing page ages quickly. Stripe and many product sites use “breathing” backgrounds—gentle colour motion that adds depth without cluttering the UI. Three.js is powerful, but for a single fullscreen light wash it is often overweight: extra bundle bytes, scene graph, camera and render loop where a fullscreen quad suffices.
We took “vanilla” WebGL: one <canvas>, vertex and fragment shaders, requestAnimationFrame. No scene graph—just a viewport-sized rectangle and a u_time uniform for animation.
Minimal architecture
The vertex shader emits a clip-space quad; the fragment shader colours pixels in UV space. A common technique blends a few noise layers or low-frequency sinusoids from normalised coordinates so you get broad blobs, not grain. Parameters—speed, saturation, contrast—live as constants or uniforms so design can tune without rewriting logic.
Cap device pixel ratio: on Retina displays devicePixelRatio can hit 2–3; rendering natively when you do not need it drains laptop batteries. We clamp with Math.min(devicePixelRatio, 2) and resize on window changes.
Accessibility and UX
A decorative background must not fight the copy. We keep contrast below headline typography and sanity-check readability in light and dark themes. For users with prefers-reduced-motion we freeze time-based animation and show a static frame—a single guard in JS before incrementing u_time.
Takeaway
This gradient is not magic—it is discipline: a tight pipeline, conscious pixel budget and respect for motion preferences. On a marketing site it reads “premium” without dragging in a heavyweight 3D stack.
Need the same visual language on your site? Book a strategy session—we will map the effect to your brand and metrics.
