Study 03 / Elastic Fabric
A surface made from shared displacement
Elastic Fabric is not a cloth or constraint solver. Its 195 or 247 points are tethered home, coupled through four-neighbor displacement differences, and strongly damped.
How much motion should neighboring elements inherit from one another?
Open the live system- Home
- 8.5
- Coupling
- 3.8
- Damp
- 4.7
- Field
- 220px
On this page
01 / Elastic Fabric / The visible seam
The lines reveal who is coupled.
A line in Elastic Fabric is more than rendering. Every horizontal and vertical seam joins two nodes whose displacements are compared in the force pass. The picture and the topology agree: if an edge is absent from the drawing, that neighbor relationship is also absent from the model.
Connection does not come from preserving the visible length of that line. Each node measures how far it has moved from home, then compares that displacement with up to four neighbors. A local error becomes a nearby force on the next frame, which is enough to make a flat grid read as one surface.
The emerald brightness is art direction, not a stress map. Line alpha increases by column and every fifth point is cyan; neither treatment reports force, strain, or priority. The model is truthful about adjacency while the palette remains editorial.
The line reveals adjacency. The force decides whether adjacency feels material.
02 / Lattice before material
Two fixed cuts define the surface.
At 760px and above, the scene uses a 19-by-13 lattice: 247 points and 462 drawn edges. Below that breakpoint it becomes 13-by-15: 195 points and 362 edges. The mobile cut trades horizontal resolution for more rows, keeping the mesh legible in portrait orientation rather than merely shrinking the desktop topology.
- Desktop cut
- 19 × 13247 points462 edges
- Mobile cut
- 13 × 15195 points362 edges
Horizontal span: min(78vw, 1040px) · vertical span: min(62vh, 620px)
The active span is capped at 78% of viewport width or 1,040px, and 62% of viewport height or 620px. Seed zero begins exactly on that regular screen-space grid with zero velocity; non-zero seeds add a small, edge-tapered initial displacement without changing topology. Resize reconstructs the transient state from the current seed, so dimensions remain coherent at the cost of losing the current deformation.
This is not a cloth or distance-constraint solver. It has no diagonal fibers, shear or bending links, edge pins, collisions, self-intersection handling, rest-length projection, or iterative constraint passes. Edge nodes simply have fewer neighbors; every point, including the interior, has its own soft route home.
- Included
- left / right / up / down
- Absent
- diagonal / shear / bend
04 / A patch, not a point
Pressing loads a neighborhood.
Fabric does not select or pin one vertex. While pressed, every node within 220px receives a force toward the pointer. The coefficient is 42, and a quadratic falloff makes the center respond strongly while the outer boundary approaches zero without a hard ring.
w(d) = (1 − d / 220)²weight = (1 - distance / 220)^2
F_pointer = 42 * weight * (pointer - point)Hover is a different input. It adds only a vertical sine force with amplitude 12, a period of about 3.14 seconds, and an x-phase wavelength of about 524px. Pointer speed does not affect either mode. Releasing a mouse removes the pressed force but leaves the weaker hover wave at the cursor; releasing touch now ends the active field because touch has no hover contract.
Links, controls, and reading copy are excluded. On touch screens, vertical movement remains available to page scrolling through touch-action: pan-y, so a vertical drag can be cancelled by browser scroll. The scene is ambient direct manipulation, not a precision grab handle.
05 / Settle before spectacle
Recovery is part of the material.
All forces are accumulated before any point moves, preventing traversal order from giving later nodes newer neighbor positions. The integrator then updates velocity, applies exponential loss, and advances position. This is one semi-implicit Euler pass rather than an iterative constraint solve.
delta = min(delta, 0.028)
velocity = (velocity + force * delta) * exp(-4.7 * delta)
position = position + velocity * deltaWithout continuing force, velocity has a half-life of about 147ms. The origin and neighbor springs continue acting, so full recovery depends on the coupled mode, not that half-life alone. There is also no fixed substep schedule: the 28ms cap prevents a delayed frame from becoming one unstable leap, but discarding excess time makes the scene briefly slow after a stall.
Strong loss is the production choice. A looser lattice would advertise every rebound and make the interface wait for its own flourish. Here the deformation travels far enough to establish connection, then the grid’s original alignment becomes the dominant visual again.
06 / One pass, then stillness
The frame budget is a construction schedule.
Per-frame work is O(points + edges). The desktop force pass checks 988 candidate neighbor slots and applies 924 valid directed contributions before drawing 462 seams and 247 points. Mobile checks 780 slots, applies 724 contributions, draws 362 seams, and fills 195 points. Reusable typed force buffers avoid allocating two new arrays on every frame, while the four neighbor offsets are shared instead of rebuilding a neighbor list per node.
- 01Force pass
Home, four-neighbor, then pointer contribution
- 02Integrate
Semi-implicit Euler with a 28ms local cap
- 03Draw
362 or 462 seams plus every lattice point
- 04Wash
A time-corrected 0.52-at-60Hz visual clear
The Canvas wash is calibrated to alpha 0.52 at the 60Hz reference and converted from delta, keeping faint visual persistence closer across refresh rates. State integration is capped separately at 28ms. The shared Canvas still caps DPR at 2 and cancels its animation frame when the document is hidden or the atlas is offscreen.
With prefers-reduced-motion: reduce, the loop never starts. Every point is placed into a deliberate diagonal wave using13 × sin(0.55 × column + 0.28 × row) at seed zero; non-zero seeds alter its bounded phase and amplitude. Horizontal offset is 36% of that value. The still renderer does not rewrite live positions or velocity. Leaving reduced-motion mode therefore resumes the preserved lattice without having advanced it or injecting a hidden static deformation into the solver.
13 × sin(0.55c + 0.28r); it is not a frozen live frame.The still is not a paused live mesh. It is a separate composition with at most about ±4.68px of horizontal and ±13px of vertical displacement. The Canvas remains aria-hidden, while explanation and navigation remain available in semantic HTML. The shared Pause / Resume transport now freezes the live lattice, its velocities, and the active phase clock without replacing them with this authored reduced-motion specimen.
07 / Where connection earns motion
Let neighbors inherit motion only when grouping matters.
Coupled response can clarify that adjacent elements belong to one object: a grouped drag affordance, a shared layout transition, or a surface whose local change should be noticed beyond one control. It earns attention when transferred motion explains structure and recovery finishes before the next decision.
- 01 / Load
Use direct manipulation in an open, bounded region.
- 02 / Transfer
Let adjacent elements inherit enough offset to reveal grouping.
- 03 / Recovery
Return alignment quickly enough that rebound never becomes the task.
- 04 / Reject
Keep decorative lattice motion away from reading, forms, and precise status.
Do not use this model when edge length, collision, folding, tearing, or pinned boundaries carry meaning. Those requirements need a real constraint system and stronger testability, not extra stiffness in a visual approximation. A CSS transition or shared-element transform is also better when only one or two elements need continuity.
Connection is not the line between two points. It is the amount of displacement those points are asked to share. If shared displacement does not explain the interface, the most disciplined coupling coefficient is zero.
Method
References and implementation sources
This article documents the live implementation running on this site. These primary standards and publication records were used to verify API behavior and technical terminology.
- HTML Canvas 2D ContextWHATWG HTML Living Standard
The rendering contract used to draw the bounded point-and-edge lattice.
- Animation framesWHATWG HTML Living Standard
The requestAnimationFrame processing model behind the time-normalized solver loop.
- Pointer Events Level 3W3C
Pointer capture and cancellation behavior for pulling and releasing the mesh.