Silk flow
Flow · WebGL shader with a CSS fallback
Soft ribbons of colour fold over one another like silk moving in slow wind. Two token colours stream diagonally across the page background, with faint highlights along the folds where they catch the light. Calm and premium: the motion is felt rather than watched, and there are no hard edges anywhere.
✓ (4×) · claude-haiku-5-5 → claude-opus-5-5# Build the "Silk flow" background effect (`silk-flow`) Family: Flow · WebGL fragment shader over a CSS fallback. Slow ribbons of two token colours fold over the background like silk in a breeze. ## Look Soft ribbons of colour fold over one another like silk moving in slow wind. Two token colours stream diagonally across the page background, with faint highlights along the folds where they catch the light. Calm and premium: the motion is felt rather than watched, and there are no hard edges anywhere. ## Parameters (current values) - Speed `--fx-speed`: 0.5 (range 0.1–2) — 1 = one slow fold every few seconds - Fold size `--fx-scale`: 1 (range 0.5–3) — higher gives more, smaller folds - Intensity `--fx-intensity`: 0.7 (range 0–1) — how much the colours cover the background - Colour A `--fx-color-a`: the `primary` colour token, `var(--c-primary)` - Colour B `--fx-color-b`: the `accent` colour token, `var(--c-accent)` - Background `--fx-color-bg`: the `bg` colour token, `var(--c-bg)` ## Recipe - Space: centre the coordinates on the canvas and divide by the canvas height so the pattern keeps its proportions, then multiply by `u_scale` (higher gives more, smaller folds). Turn the frame about 30° so the ribbons stream from lower left to upper right. Time is slow: no phase in the shader should advance faster than about 0.3 radians per second of `u_time`, and the field as a whole must not scroll; it drapes in place. - Folding field, made only from sines and cosines (no hash, value or gradient noise): start from the turned coordinate and nudge it three or four times in a row. Each nudge shifts one axis by a sine of the other axis plus its own slow drift in time, so every wave bends the ones after it and the bends read as folds. The first nudge is the big one: its wavelength is about the canvas height and its shift is about one and a half ribbon spacings, so each ribbon visibly swings 30–60° off its average direction and back within the canvas. Each later nudge has its own direction, a frequency at an uneven ratio to the others (not a double or simple fraction) and roughly half the shift of the one before. The ribbons must also crowd together and spread apart along their length, never stay evenly spaced like stripes, but must not cross or loop. - Ribbons: read the folded coordinate across the flow direction and pass it through a smooth periodic ramp, so about four ribbons span the canvas height at `u_scale` 1. Shape it as a gradient, not a stripe: full colour only on a narrow crest in the middle of each ribbon, easing out over about two-thirds of the spacing to the gap, so no edge can be pointed at. - Colour, starting from `u_color_bg` so the background shows through: lay `u_color_a` over the ribbon crests at up to 0.85 × `u_intensity`, and `u_color_b` in the gaps at up to half that. Fade both with a second, much broader and slower wave across the page, so some regions sink almost to the background: at intensity 0.7 about a third of the canvas should read as plain background, and nowhere is fully saturated colour A or B. - Sheen: along each ribbon's shoulders only (halfway between crest and gap), add a thin highlight of the average of colours A and B, peaking at 12% × `u_intensity` and falling to zero at crests and gaps. - Edges: fade toward `u_color_bg` starting about 60% of the way from the centre to the corners, reaching the plain background at the corners. Clamp to 0–1 and output opaque colour. ## CSS fallback The element's own background: `--fx-color-bg`, under two large soft radial gradients — `--fx-color-a` centred at 30% 35% (ellipse 70% × 60%) and `--fx-color-b` at 75% 70% (ellipse 65% × 60%), each from `color-mix(in srgb, <colour> calc(var(--fx-intensity) * 70%), transparent)` to transparent at 70% — plus a 120deg linear gradient from `--fx-color-a` at 25% strength through transparent to `--fx-color-b` at 25%. Static; it should read as the shader's still frame blurred. ## Runtime rules - Mount it in one element that fills a fixed, `pointer-events: none`, `aria-hidden` layer behind the page content; every parameter above is a CSS custom property on that element. - Colours come only from the colour-token variables above (mix them with `color-mix()` or alpha), never hard-coded hex, so the effect follows any palette and light or dark mode. - Two layers. A CSS background on the element is the fallback and must look complete alone (described above): it is all that shows without WebGL or after a lost context. A full-size `<canvas>` on top draws the shader. - Plain WebGL 1: one fragment shader over a full-screen triangle; no libraries, CDN, textures or images; script under ~8 KB. - Uniforms: `u_resolution` (canvas size in pixels), `u_time` (seconds, already multiplied by the speed parameter) and one per parameter except speed: `u_scale` (float), `u_intensity` (float), `u_color_a` (vec3 RGB 0–1, read from the CSS variable), `u_color_b` (vec3 RGB 0–1, read from the CSS variable), `u_color_bg` (vec3 RGB 0–1, read from the CSS variable). Output opaque colour. - Cap the device pixel ratio at 2 (1.5 on phones) and the frame rate at 30 fps on phones; pause when the tab is hidden or the canvas is off screen; release the context when it leaves the screen. - With prefers-reduced-motion, or a `?shot` URL flag (screenshots), draw one frame at `u_time = 2` and stop. No WebGL, or a lost context: remove the canvas and leave the CSS fallback. ## Avoid - Hard edges, stripes or a visible noise grid - A third hue: only colour A, colour B and the background - Fast motion: at speed 1 a fold should take several seconds to move across a card - Highlights brighter than the sheen above (12%) or white patches that drop text contrast - Textures, images, a noise library, or hash-based noise; and any code or constants lifted from published shaders or tutorials: write the waves yourself
Copied!