No.168 · Backgrounds· New
Phantom Threads
Long strands of light swaying across a dark field like a long-exposure light painting: hot white cores, wide soft halos, a faint colour fringe, and pulses travelling along each thread. The pointer warms the strands it passes.
The prompt
Written for the variant you picked above: Violet
Write a WebGL1 full-screen fragment shader background (no libraries): about 26 strands of light (60% as many under 640px) running from bottom to top across the whole width, leaning about 18° and each swaying on two slow sine waves of different frequency and phase, so neighbours drift in and out of each other. Each strand gets fixed random traits from its index: position jitter, lean, brightness and a depth: near strands are sharp (a core about 0.16% of the height wide), far ones are out of focus — up to ten times wider and half as bright — so the field has depth of field. For every pixel, sum the strands: a Gaussian core in the core colour, sampled three times with a sub-pixel horizontal offset per channel so the edges carry a faint red/blue fringe; an exponential halo ten times wider in the glow colour; and a very wide faint haze. Modulate each strand by a pulse of light travelling up its length at its own speed, and fade them gently towards the top and bottom. Tone-map the sum with 1 − exp(−x) so overlaps bloom instead of clipping, and add it over a vertical gradient from the ground to the haze colour, with a soft vignette. The pointer warms the strands near it (up to 2.6× brighter in a soft circle), easing in and out. Render at 0.8× device pixels (lower and about 30fps on touch), pause offscreen and in hidden tabs, draw one still frame under reduced motion, and fall back to CSS stripes without WebGL. Children sit above the canvas. Selected variant — Violet (violet): Palette { ground #06041a, haze #130b36, glow #7d5cff, core #efe8ff }: violet threads on deep indigo. 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 across the threads to warm the ones near it. Motion: Strands sway and pulse continuously; the pointer's warmth eases in and out (0.06 per frame). Reduced motion draws one still frame. Accessibility: Decorative and hidden from assistive tech. Cores can be bright where strands cross; keep a scrim behind text. Responsive behavior: Fills its container; fewer strands under 640px; device pixel ratio capped at 2. Touch: No pointer effect on touch; the threads keep moving on their own. 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 across the threads to warm the ones near it.
- Motion
- Strands sway and pulse continuously; the pointer's warmth eases in and out (0.06 per frame). Reduced motion draws one still frame.
- Accessibility
- Decorative and hidden from assistive tech. Cores can be bright where strands cross; keep a scrim behind text.
- Responsive
- Fills its container; fewer strands under 640px; device pixel ratio capped at 2.
- On touch
- No pointer effect on touch; the threads keep moving on their own.