Skip to content

No.174 · Backgrounds· New

Storm Veil

Smoke rolling through a storm: three layers of warped noise make deep folds and drifting veils, with fine silky strands drawn along the currents. A slow eddy turns around the pointer. Comes dark or pale. A background only, with no text of its own.

The prompt

Copy this text

Automatic copying is unavailable. Copy the selected text using your device’s copy command.

Written for the variant you picked above: Midnight

Write a WebGL1 full-screen fragment shader background (no libraries): rolling storm smoke, seen flat-on. Take the position in screen heights × 1.15 and domain-warp it twice (Inigo Quilez style): q = two fBm lookups of p drifting in opposite directions; r = two fBm lookups of p + 4q; the smoke density f = fBm(p + 3.6r). Five octaves of quintic value noise with a rotation between octaves keep it free of grid artefacts. Turn the density into cover with smoothstep(cover, cover + 0.32, f), where cover sets how much of the frame is smoke and how much is open void; mix void → body colour by it, then towards a light colour where f is highest. Draw silky strands along the currents: pow(1 − |sin((2r.x + q.y) × 14)|, 10), added faintly inside the smoke and more strongly near its thin edges. The pointer stirs a slow eddy: rotate the position around it by up to 1.3 radians, falling off as a Gaussian. Everything drifts slowly (time × 0.035). Render through a small WebGL1 harness: a full-screen triangle, the device pixel ratio capped at 2 and scaled down (and about 30fps) on touch, paused offscreen and in hidden tabs, one still frame under reduced motion, the pointer eased in with a slow lerp and released when it leaves, and a CSS gradient fallback without WebGL. Add a little per-pixel noise so the gradients never band. An optional fade prop softens the bottom edge into the ground colour: a gradient to the ground plus a backdrop blur masked to grow towards the edge. Children sit above the canvas. Selected variant — Midnight (midnight): Navy smoke on near-black, mostly open void: void #010209, body #323e62, light #a3b4dd, cover 0.29. This selection takes precedence over references to other themes or options in the general brief. Implement this selected appearance; do not add a variant picker or alternative appearances unless requested. Implementation requirements: Use React and TypeScript. Keep the component self-contained, with uniquely scoped CSS and no animation libraries. Include required imports, styles and font setup in the result. Interaction: Move the pointer to stir a slow eddy in the smoke. Motion: The folds drift and turn slowly. Reduced motion draws one still frame. Accessibility: Decorative and hidden from assistive tech. The dark looks suit white text; the pale look is mid-toned, so give text a scrim or a solid panel. Responsive behavior: Fills its container at any aspect ratio; device pixel ratio capped at 2. The optional fade softens the bottom edge into the ground colour. Touch: No eddy on touch; the smoke keeps drifting. Preserve keyboard access, visible focus and reduced-motion behavior. Keep fictional demo data and simulated service calls in a separate usage example; expose callbacks for real actions and recover from rejected requests. Keep usage-example links inside the demo: use local buttons or prevent navigation. Demonstration links must not navigate to Vitrine routes or open other pages; preserve real URL support in the reusable component itself. Verify the result at narrow and wide viewport sizes, with keyboard input and reduced motion enabled.

Notes

Interaction
Move the pointer to stir a slow eddy in the smoke.
Motion
The folds drift and turn slowly. Reduced motion draws one still frame.
Accessibility
Decorative and hidden from assistive tech. The dark looks suit white text; the pale look is mid-toned, so give text a scrim or a solid panel.
Responsive
Fills its container at any aspect ratio; device pixel ratio capped at 2. The optional fade softens the bottom edge into the ground colour.
On touch
No eddy on touch; the smoke keeps drifting.

Loading components…