[ specimens ] [ index ]

[ check out my other projects ↗ ]

Specimens

Interaction studies in plain HTML, CSS and JavaScript, sorted into families. Every tile is live, and new ones keep arriving.

Under each tile, [ view code ] opens the complete file and [ copy ] puts it on your clipboard. All of it is public domain.

A growing catalogue · no libraries
Featured · 42 Topographic metaballs[ go to specimen ]

Depth & light

Perspective, layers and light: flat screens pretending to have a third dimension.

19 specimens

01Ridgeline parallax

Clip-path layers

move · scroll the pagedrag · scroll the page

y = Σ (1 − |sin(f·x + φ)|) / k7 layers

depth 0.15 → 1.00 · lerp 6% / frameclip-path · translate3d

100%

Seven mountain ridges stacked by depth. Near ridges travel farther than distant ones, so the scene reads as three-dimensional with no 3D engine at all.

Move your pointer across the scene, then scroll the page and watch the near ridges rise faster than the far ones.

Technique
clip-path polygons, translate3d
Inputs
Pointer position, scroll offset
Layers
7, depth 0.15 → 1.00
Easing
Lerp, 6% per frame

02Holographic foil card

Blend modes

hover to tilt · click to flipdrag to tilt · tap to flip

θ = spring(k 170, c 18) · ±18°color-dodge · overlay

foil + glare follow the lightpreserve-3d

70%

A trading card that tilts toward your pointer on a damped spring. A rainbow foil and a glare highlight slide across it through blend modes, so the shine follows the light.

Hover over the stage to tilt the card. Click it, or press Enter when it has focus, to flip it.

Technique
preserve-3d, color-dodge, overlay
Inputs
Pointer position, click
Spring
Stiffness 170, damping 18
Tilt range
±18° on both axes

04Point sphere

Projection

drag to throw · hover to bulgedrag to throw

s = f / (f − z) · θ = i · 137.5°900 points

friction e^(−1.8t) · idle 0.18 rad/scanvas 2d

Nine hundred points spread evenly over a sphere with the golden-angle spiral, rotated and projected with plain trigonometry. Nearer points grow larger and brighter, and your pointer raises a bulge on the side facing you.

Drag to spin the sphere and let go to throw it. Hover over its face to push the points out.

Technique
Fibonacci sphere, perspective projection on canvas
Points
900, drawn back to front
Throw
Drag velocity with exponential friction

05Extruded type

Stacked slices

move to turn · click for a new worddrag to turn · tap for a new word

z = −1.6 px · i28 slices

spring k 120 · c 14 · tilt ±28°preserve-3d

A word built from 28 copies of itself, each pushed 1.6 px further back in 3D space and shaded darker. Together they read as a solid block of type that turns toward your pointer.

Move your pointer around the stage to turn the block. Click to change the word.

Technique
preserve-3d, stacked translateZ slices
Depth
28 slices × 1.6 px
Tilt
±28° on a spring

06Layer explode

Exploded view

click to explodetap to explode

z = p · (i − 2) · 40 px · rotate 52° / −30°5 layers

spring k 140 · c 17preserve-3d

A notification card pulled apart into the five layers it is built from, like an exploded technical drawing. One spring drives the separation, the isometric turn and the labels.

Click to explode or collapse the card. Move your pointer to swing it a little.

Technique
preserve-3d, translateZ per layer
Layers
Shadow, surface, texture, content, focus ring
Spring
Stiffness 140, damping 17

07Halftone light

Lambert shading

move the lampdrag to swing the light

size = base + (N · L − flat) · 1.15 px dots

lamp eases after the pointercanvas 2d

A raised word printed in halftone dots. Each dot's size is a base that shows the letters, plus how much light its patch of slope catches, so the sides facing the lamp lighten and the far sides fall into shadow.

Move your pointer to carry the lamp. At the centre it shines from overhead; toward the edges it rakes in low and the relief deepens.

Technique
Height map → normals → Lambert shading
Grid
5 px dots
Light
Follows the pointer, 72° overhead at the centre to 38° at the edges

08Paper fold

Hinged panels

click to foldtap to fold

top leads · bottom trails by 35%3 panels

shade = sin((1 − open) · π) · 0.35preserve-3d

A letter folded in thirds. Unfolding, the top flap leads and the bottom follows; folding, the order reverses. Each flap darkens as it turns away from the light.

Click to fold or unfold the letter.

Technique
preserve-3d hinged panels
Panels
Three thirds, front and back faces
Spring
Stiffness 120, damping 15

09Focus pull

Depth of field

move up and down to focusdrag up and down to focus

blur = |z − focus| / 34 px11 cards

rack spring k 60 · c 13css filter

Eleven cards stand at different depths, and each one blurs by how far it sits from the focal plane, like a wide-open lens. A spring racks focus from card to card with a slight lag, the way a focus puller turns the wheel.

Move up and down the stage to turn the focus: top is far, bottom is near. Click or tab to a card to snap to it.

Technique
CSS 3D depth, blur by distance from the focal plane
Blur
1 px per 34 px of depth, up to 9 px
Focus
Spring k 60, c 13

10Rolling die

Edge pivot

click or arrow keys to rollswipe to roll

p′ = pivot + R(edge, θ)·(p − pivot)7 × 5 board

quarter turn · 260 mscanvas 2d

A die tips over its bottom edge one square at a time, a quarter turn about that edge. Its orientation is kept as a rotation matrix, so the pips facing up always agree with the way it rolled.

Use the arrow keys, click beside the die, or swipe to roll it. Rolling into an edge only rocks it.

Technique
Rodrigues rotation about the leading edge
Board
7 × 5 squares, visited squares glow
Roll
260 ms, eased in and out

11Shadow casting

Visibility polygon

move the lamp · drag blocksdrag to move the lamp

ray → nearest wall, sorted by angle6 blocks

3 samples · soft edgescanvas 2d

A lamp over a floor of blocks. Rays go out to every block corner and stop at the first wall they hit; joined in order, the hits outline everything the lamp can see. Three lamp positions a few pixels apart soften the shadow edges.

Move the lamp with your pointer. Drag a block to move it.

Technique
Visibility polygon by ray casting
Rays
3 per corner, nudged either side
Penumbra
3 lamp samples

12Glass lens

Barrel distortion

move the lens · click for powerdrag the lens · tap for power

r_src = r·(1 − k + k·r²)×1.5 · ×2 · ×3

per-channel k · colour fringeimagedata

A magnifier over a page of type and graph paper. Each pixel inside the lens reads from a point nearer its centre, so the middle is enlarged and the rim bends straight lines. Red and blue bend by slightly different amounts, which fringes the edge like real glass.

Move the lens with your pointer. Click to switch between ×1.5, ×2 and ×3.

Technique
Per-pixel radial remap, ImageData
Mapping
r_src = r · (1 − k + k·r²)
Fringe
Red 6% stronger, blue 6% weaker

13Isometric field

Isometric projection

move over it · click to rippledrag over it · tap to ripple

x = (i − j)·w/2 · y = (i + j)·w/4 − h196 columns

ring speed 6 cells/scanvas 2d

A grid of columns in isometric projection, drawn from the back corner forward so nearer columns cover farther ones. Each height is a spring chasing a slow swell and a bump under the pointer; a click sends a ring across the field.

Move over the field to raise it. Click to start a ripple.

Technique
Isometric projection, painter's order
Grid
14 × 14 columns
Springs
k 140, c 14 per column

14Lenticular card

Interleaved strips

move to tilt · click to swapdrag to tilt · tap to swap

frame = round(tilt·(n − 1) + x·0.55)5 px ridges

rotateY ±22° · sliding sheencanvas + css 3d

A ridged card hiding several pictures in thin interleaved strips. Which strip each ridge shows depends on the viewing angle, and that angle changes slightly across the card, so a tilt sweeps the change from one edge to the other.

Move sideways to tilt the card. Click to swap between the wink and the moon phases.

Technique
Interleaved strips chosen by angle
Strips
5 px per ridge
Cards
Wink, 3 frames · phases, 4 frames

15Platonic solids

Back-face culling

drag to spin · click for the nextdrag to spin · tap for the next

face ⇔ every corner behind its plane5 solids

cull n·z ≤ 0 · hidden edges dashedcanvas 2d

The five regular solids, written down only as lists of corners. Faces are found by brute force: a plane through three corners is a face when every other corner lies behind it. Faces turned away are culled and their edges dashed, like hidden lines on a technical drawing.

Drag to spin and throw. Click to step to the next solid.

Technique
Brute-force convex hull, back-face culling
Solids
Tetrahedron through icosahedron
Shading
Flat, by angle to the light

16Light shafts

Radial blur

move the light · click for blindsdrag the light · tap for blinds

buffer += scale(buffer, sᵢ, at light)5 passes

40% buffer · additivecanvas 2d

Light streaming past a word. A small buffer holds the light with the word blacked out over it, then it is smeared outward from the light by drawing it onto itself at growing scales. The gaps between letters stretch into beams.

Move the light with your pointer. Click to swap the word for window blinds.

Technique
Screen-space radial blur
Passes
5, scaled 1.06 to 2
Buffer
40% resolution

17Page curl

Fold reflection

drag the corner

x′ = x − 2((x − m)·n)·n4 pages

springs back · turns past halfwaycanvas 2d

Peeling a page is a reflection. The fold is the line halfway between the corner and your finger; everything past it is mirrored across that line and shows the paper's back, while the page below shows through. Let go past the middle and the page turns.

Drag the bottom-right corner. The turn page button flips it without dragging.

Technique
Reflection across the perpendicular bisector
Clipping
Sutherland–Hodgman against the fold
Pages
4, looping

18Perspective room

Vanishing point

move to look arounddrag to look around

screen = c + (p − eye)·f / z4 frames

back-face test for the plinthcanvas 2d

A small gallery seen from inside, drawn with nothing but division by depth. Moving your eye sideways shifts near things more than far ones, and that difference is all the depth the picture needs.

Move your pointer to look around the room.

Technique
One-point perspective
Projection
screen = centre + (p − eye)·f / z
Eye
Leans up to 42% of the room width

19Wire terrain

Perspective divide

steer · raise to fly faster

screen = world · f / z44 × 40 grid

hills = Σ sin(a·x + b·z)fog to blue

An endless wireframe landscape flying toward you. Hills come from three crossed sine waves, each grid point is projected by dividing by its distance, and far rows fade into blue haze.

Move your pointer left and right to steer. Raise it to fly faster, lower it to slow down.

Technique
Perspective divide on canvas, no 3D library
Grid
44 × 40 points
Terrain
Three crossed sine waves with a valley

Physics

Springs, gravity and pressure, worked out one frame at a time.

19 specimens

20Spring dot field

Canvas springs

sweep · click for a shockwavesweep · tap for a shockwave

a = k·(home − x) − c·v + push—

radius 110 px · ring 560 px/scanvas 2d

120 9

A grid of dots, each tied to its home position by its own spring. Your pointer pushes them aside, and a click sends a shockwave rippling outward.

Sweep your pointer through the grid and click anywhere. Lower the damping to make the dots wobble longer.

Technique
Canvas 2D, per-dot spring
Inputs
Pointer repels, click ripples
Push radius
110 px

21Gooey blobs

SVG filter

merge · click to flingdrag to merge · tap to fling

α′ = 22·α − 9 after blur σ6 + 1 blobs

feGaussianBlur → feColorMatrixsvg filter

14 px

Blurring a group of circles and then sharpening the blur's edge back to a hard line makes nearby shapes melt into each other, like drops of liquid.

Move your pointer into the orbiting blobs to merge with them. Click to fling off droplets that get pulled back in.

Technique
feGaussianBlur + feColorMatrix
Inputs
Pointer on a spring, click spawns drops
Alpha curve
a × 22 − 9

22Flocking boids

Steering rules

chase · click to scatterchase · tap to scatter

a = separate + align + cohere + flee30–140 birds

sight 50 px · space 20 px · fear 110 pxreynolds 1987

Each bird follows three local rules: keep some distance, match its neighbours' heading, and drift toward the group. Flocks emerge from that alone. Your pointer is a predator.

Chase the flock with your pointer, or click to scatter it.

Technique
Boids, after Craig Reynolds (1987)
Birds
30 to 140, scaled to the stage
Sight
50 px, personal space 20 px

23Verlet cloth

Verlet integration

grab · yank to tear

x′ = 2x − xₚ + a·dt²600 points

4 passes · snaps at 2.6×canvas 2d

A sheet of 600 points held together by springy links, hanging from pins. Points remember where they were a frame ago, and that difference is their speed. Pull too hard and links snap.

Grab the cloth and drag it around. Yank fast to tear it, then press new cloth.

Technique
Verlet integration with distance constraints
Grid
30 × 20 points, 4 solver passes
Tearing
Links snap past 2.6× their length

24Slosh meter

Spring chain

drag the level · shake

vᵢ += −k·hᵢ + s·(hᵢ₋₁ + hᵢ₊₁ − 2hᵢ)48 springs

level spring k 26 · c 7canvas 2d

A progress gauge with a liquid inside. The surface is a row of springs that pass energy to their neighbours, so changing the level or shaking the glass sends waves across.

Drag up and down to set the level. Move sideways quickly to shake it.

Technique
1D spring chain with neighbour spreading
Surface
48 springs
Level
Spring k 26, c 7

25String harp

Web audio

strum · turn sound onswipe across · turn sound on

y = A·e^(−1.6t) · sin(2πft)8 strings

triangle → low-pass · 1.8 s ringweb audio

Eight strings tuned to a pentatonic scale, so any strum sounds right. Each string bows out and rings down when you cross it. Sound is off until you turn it on.

Sweep your pointer across the strings. Press sound off to hear them.

Technique
Crossing detection, Web Audio
Scale
C pentatonic, C4 to E5
Voice
Triangle wave through a falling low-pass

26Orbit sandbox

Inverse square

pull back · release

a = G / r² toward the starup to 12 bodies

velocity verlet · 3 s previewcanvas 2d

A star and its planets under real inverse-square gravity. Drag to launch a new planet like a slingshot, and a dotted line shows where it will go before you let go.

Press, pull back and release to launch a planet. Watch the preview to aim for an orbit.

Technique
Velocity Verlet, 4 substeps
Gravity
a = G·m / r²
Preview
3 s simulated ahead

27Soft-body jelly

Pressure body

grab and throw

F = k·(d − d₀) + p·(A₀ − A) / A₀28 points

8 substeps · bounce 0.35canvas 2d

A blob made of a springy skin with air pressure inside. The skin keeps its edge lengths, the pressure keeps its area, and between the two it squashes, wobbles and recovers.

Grab the jelly and throw it at the walls.

Technique
Spring skin plus area pressure
Skin
28 points, 8 substeps
Pressure
Pushes edges out by the area deficit

28Newton's cradle

Momentum exchange

pull a ball and let go

va′, vb′ = vb, va5 balls

16 substeps · e 0.995canvas 2d

Five pendulums whose balls just touch. When two meet and are closing, they swap speeds, which is what an elastic collision between equal masses does. Repeating that pass along the row many times a frame carries a hit straight through to the far end.

Pull one or two balls aside and let go.

Technique
Pendulums plus sequential speed exchange
Substeps
16 per frame
Restitution
0.995

29Ball pit

Circle collisions

push through · click to kickdrag through · tap to kick

x′ = x + (x − xₚ) + g·dt²~200 balls

4 relaxation passes · hash gridcanvas 2d

Hundreds of Verlet balls in a box. Every step they fall, then a few passes push apart any pair that overlaps, keep them inside, and shove them out of the pointer's disc. A grid of buckets means each ball only checks its neighbours.

Push through the pile. Click to kick the balls near the pointer upward.

Technique
Verlet integration, overlap relaxation
Passes
4 per frame
Neighbours
Spatial hash grid

30Iron filings

Dipole field

drag a magnet · click to flipdrag a magnet · tap to flip

B = Σ q·(p − pole) / |p − pole|³2 magnets

length ∝ log |B|canvas 2d

Two bar magnets and a scatter of filings. Each magnet is a pair of poles, and the field anywhere is the sum of their pulls. Every filing turns toward it on a spring, longer and darker where the field is strong.

Drag a magnet to move it. Click one to flip it end for end.

Technique
Pole pairs, field summed per filing
Filings
One per 11 px, jittered
Turning
Spring toward the field, either end first

31Double pendulum

Sensitive dependence

drag a bob · click to restartdrag a bob · tap to restart

θ″ from the Lagrangian · rk42 pendulums

start 0.001 rad apartcanvas 2d

Two double pendulums, identical except that one starts a thousandth of a radian further round. For a few seconds they move as one; then the gap doubles and doubles again until their paths have nothing in common.

Drag either bob to pose them, then let go. Click empty space to restart from the current pose.

Technique
Lagrangian equations, Runge–Kutta 4
Offset
0.001 rad on the second arm
Steps
8 per frame

32Particle fluid

Density relaxation

stir itdrag to stir

P = k(ρ − ρ₀) · Pₙ = kₙ·ρₙ~800 particles

2 steps a frame · grid neighbourscanvas 2d

Water made of particles. Each one measures how crowded it is twice: a plain density that pushes toward a resting value, and a near density that only ever pushes apart. Neighbours are nudged by both, and velocity is simply how far a particle moved.

Stir the water with your pointer. Left alone, the box tilts and the water sloshes.

Technique
Double density relaxation (Clavet et al., 2005)
Particles
Up to 1,400, reach 22 px
Foam
Fast or thinly surrounded particles whiten

33Grass field

Damped springs

sweep through itswipe through it

α″ = k(lean + wind − α) − c·α′~550 blades

push ∝ pointer speedcanvas 2d

Hundreds of blades, each a damped spring rooted in the ground. Wind is a slow travelling wave plus gusts, so neighbours lean together, and the pointer pushes blades away harder the faster it moves. Back rows are shorter and paler.

Sweep your pointer through the grass.

Technique
Angular spring per blade
Rows
6, paler and shorter toward the back
Wind
Travelling sine plus two slow gusts

34Buoyancy

Archimedes

drag a block and drop it

lift = ρ·g·A_under at its centroid3 blocks

6 substeps · righting torquecanvas 2d

Blocks of different densities in water. Each outline is cut by the waterline; the part below is the displaced water, and it pushes up through its own centre. A block floats with the same fraction under as its density, turning until the two forces line up.

Drag a block anywhere and let go. Try pushing one under.

Technique
Submerged polygon area and centroid
Densities
0.25, 0.55, 0.85
Surface
64 springs, stirred by the blocks

35Gear train

Gear ratios

grab a gear and turndrag a gear to turn it

ω₂ = −ω₁ · n₁ / n₂5 gears

mesh offset keeps teeth in gapscanvas 2d

Five meshing gears. Gears in contact move the same distance at their rims, so each turns at minus the ratio of their tooth counts. Every angle comes from the first gear's angle plus an offset that keeps teeth in gaps.

Grab any gear and turn it; the whole train follows and coasts.

Technique
Angle chained through tooth ratios
Teeth
24, 12, 30, 9, 18
Motor
0.5 rad/s when idle

36Magnet pendulum

Basins of attraction

click to drop the bobtap to drop the bob

a = −k·p + Σ (mᵢ − p)/dᵢ³ − c·v3 magnets

basin map fills in livecanvas 2d

A pendulum over three magnets. Which one it settles on is chaotic: start points a hair apart can finish on different magnets. Behind the live bob, a map of every start point and its magnet fills in, and its borders are fractal.

Click anywhere to drop the bob there.

Technique
Spring, softened attraction, friction
Map
3 px cells, a few rows each frame
Magnets
3, 120° apart

37Fireworks

Ballistics

click to launchtap to launch

v₀ = √(2·g·h)4 kinds

drag e^(−1.6t) · trails by fadingcanvas 2d

Shells are aimed to peak where you click: the launch speed that reaches a height is the square root of twice gravity times that height. At the top they burst into sparks that keep the shell's motion, then fall under gravity and drag.

Click where a shell should burst.

Technique
Ballistic particles with drag
Bursts
Peony, ring, willow, crossette
Trails
Last frame faded, never cleared

38Pendulum wave

Phase drift

click to restart in phasetap to restart in phase

θᵢ = cos(2π · (18 + i) / 30 · t)15 pendulums

realigns every 30 scanvas 2d

Fifteen pendulums, each tuned to swing once more per cycle than its neighbour. They drift in and out of step, tracing travelling snakes, splits and braids, and line up again every 30 seconds.

Watch the patterns form. Click to restart every pendulum in phase.

Technique
Closed-form cosine per pendulum on canvas
Tuning
18 to 32 swings per 30 s cycle
View
From above the rail, so depth reads as drop

Simulation & math

Fields, automata and transforms where simple rules draw complicated pictures.

17 specimens

39Pointer ribbons

Eased chains

move in loopsdrag in loops

pᵢ += (pᵢ₋₁ − pᵢ) · e3 × 40 points

e 0.14 / 0.22 / 0.35 · quadratic midpointscanvas 2d

Three ribbons chase your pointer. Each is a chain of points where every point eases toward the one ahead of it, so the tail swings behind like a silk streamer.

Move your pointer in loops and quick flicks.

Technique
Canvas 2D, eased point chains
Points
3 ribbons × 40
Smoothing
Quadratic curves through midpoints

40Falling sand

Cellular automaton

press to pour

if empty(below) fall else slide diagonally4 px grains

bottom-up sweep · alternating sidesimagedata

A cellular automaton. Each grain checks the cell below it, then the two diagonals, and moves into the first empty one. Piles, slopes and avalanches come out of that one rule.

Press and drag to pour sand. Clear the box to start over.

Technique
Cellular automaton on a pixel grid
Rule
Down, else down-left or down-right
Grain
4 px, 1 in 20 is blue

41Fourier epicycles

Fourier series

draw a closed shape

z(t) = Σ cₖ · e^(i·2πkt)160 circles

dft · sorted by amplitudecanvas 2d

Any closed drawing can be rebuilt from circles spinning at whole-number speeds. Draw a shape and a discrete Fourier transform turns it into a chain of circles that trace it back.

Draw a closed shape on the stage. Lower the circles slider to see how few it takes to get close.

Technique
Discrete Fourier transform of the path
Samples
160 points, evenly spaced along the stroke
Order
Largest circles first

42Topographic metaballs

Marching squares

move to add a blobdrag to add a blob

f = Σ r² / d²6 levels

marching squares · 7 px cellscanvas 2d

Six drifting blobs and your pointer add up to one height field, drawn as contour lines like a hiking map. Marching squares finds where each height crosses the grid.

Move your pointer into the stage; it becomes another blob the lines bend around.

Technique
Metaball field, marching squares
Levels
6 contours, one highlighted in blue
Grid
7 px cells

43Voronoi cells

Nearest seed

move · click to plantdrag · tap to plant

cell(p) = argmin |p − sᵢ|22+ seeds

edge when d₂ − d₁ < 1.2 pximagedata

Every point on the stage belongs to its nearest seed. The borders are where two seeds tie, so the cells reshape themselves as the seeds drift.

Move your pointer to carry a seed of your own. Click to plant one where you are.

Technique
Nearest and second-nearest seed per pixel
Seeds
22 drifting, up to 48 with clicks
Edges
Where the two distances nearly tie

44Infinite zoom

Self-similar

scroll or drag to dive

sₖ = s₀ · 1.32^(frac − k)16 frames

θₖ = (k − frac) · 0.21 radcanvas 2d

An endless dive through nested frames, each a little smaller and a little turned. Only the fractional part of the depth decides the picture, so the zoom never has to stop.

Scroll or drag up and down to dive faster or climb back out.

Technique
Self-similar frames, fractional depth
Step
1.32× smaller, 0.21 rad turn
Marks
Every fifth frame in blue

45Game of Life

B3/S23

draw to add cells

born on 3 · survives on 2 or 38 px cells

11 generations a secondcanvas 2d

Conway's rules on a grid that wraps at the edges. A dead cell with exactly three live neighbours is born, a live cell with two or three survives, and every other cell dies. Newborns show in blue.

Draw on the grid to add cells. Reseed for a fresh random board.

Technique
B3/S23 on a torus
Cells
8 px
Tick
90 ms a generation

46Reaction-diffusion

Gray–Scott

paint · pick a presetdrag to paint

v′ = Dᵥ∇²v + uv² − (F + k)v3 presets

10 steps a frame · 3 px cellsimagedata

Two simulated chemicals. One is fed in everywhere, the other eats it to make more of itself and slowly decays, and both spread, one twice as fast. Two numbers, the feed and kill rates, decide whether you get coral, dividing cells or a maze.

Paint on the stage to add the second chemical. Switch between the presets.

Technique
Gray–Scott model
Grid
One cell per 3 px, 10 steps a frame
Presets
Coral, cells, maze

47Harmonograph

Damped sinusoids

click for the next ratiotap for the next ratio

x = Σ Aᵢ·sin(fᵢt + pᵢ)·e^(−dᵢt)7 ratios

detune ±0.01 · decay 0.012–0.02canvas 2d

A pen moved by pendulums that each swing at their own frequency and slowly lose energy. Near-whole-number ratios close into figures, a slight detune lands each loop beside the last, and the decay draws them inward.

Watch it draw. Click to start the next ratio.

Technique
Sum of damped sines on each axis
Ratios
2:3, 3:4, 1:2 and four more
Colour
Blue to ink as the swing dies

48Lorenz attractor

Strange attractor

drag to turn

ẋ = σ(y − x) · ẏ = x(ρ − z) − y · ż = xy − βz3 points

rk4 · h 0.005canvas 2d

Three points following the Lorenz equations, started almost together. They loop round one wing, then the other, in an order no one can predict, and before long they part for good.

Drag to turn the figure.

Technique
Lorenz system, Runge–Kutta 4
Parameters
σ 10, ρ 28, β 8/3
Trails
900 points each

49Fractal tree

Recursive branching

click to grow · move for windtap to grow · drag for wind

child = 0.68–0.82 × parent at ±0.32–0.6 rad10 levels

bend ∝ depth^1.5canvas 2d

One rule applied to itself: a branch ends by splitting into two shorter, thinner branches. Random angles and lengths make every tree different, and the wind bends twigs more than limbs.

Click to grow a new tree. Move sideways to push the wind.

Technique
Recursive branching
Depth
10 levels, growing in over 1.8 s
Wind
Stronger toward the twigs, toward the pointer

50Flow field

Noise field

move to stirdrag to stir

θ = noise(x, y, t) · 4π1,600 particles

whirl ∝ 1 / d²canvas 2d

Smooth noise gives every point on the stage an angle. Particles walk that way and leave faint marks, so the field draws itself as streamlines. The noise drifts over time, and the pointer stirs a whirlpool.

Move your pointer to stir. Double-click for a new field.

Technique
3D value noise as an angle field
Particles
1,600, respawning
Trails
Faded 6% a frame

51Julia set

Escape time

move to change cdrag to change c

z ← z² + c until |z| > 290 iterations

n + 1 − log₂(log |z|)imagedata

For every pixel, square it and add c, over and over, and count the steps before it escapes. Points that never escape form the Julia set for that c. Your pointer picks c, so the set morphs between dust, dendrites and spirals.

Move your pointer to change c.

Technique
Escape time, smoothed colouring
Iterations
Up to 90
Resolution
One sample per 2.2 px

52Maze solver

Depth-first carving

click for a new mazetap for a new maze

carve: depth-first · solve: breadth-firstone route

flood one ring a framecanvas 2d

A depth-first walk carves the maze, knocking down walls to random unvisited neighbours and backing up when stuck. Then a breadth-first flood spreads from the entrance; the first time it reaches the exit, its trail back is the shortest path.

Watch it carve and solve. Click to start a new maze.

Technique
Recursive backtracker, then breadth-first search
Maze
Perfect: one route between any two cells
Cells
12 to 22 px

53Circle packing

Grow to touch

click to planttap to plant

grow while dᵢⱼ > rᵢ + rⱼ + 2no overlaps

random seeds · ever smallercanvas 2d

Seeds land at random free points and grow until they touch a neighbour or the edge. Later seeds have to fit the gaps, so the circles shrink as the space fills, the way bubbles and pebbles pack.

Click to plant a seed where you point.

Technique
Grow until touching
Gap
2 px between circles
Restart
Once nothing over 3.5 px fits

54Galton board

Binomial

click to drop 30tap to drop 30

bin = number of rights11 rows

expected = n·C(11, k)/2¹¹canvas 2d

Every peg sends a ball left or right with even odds. The bin a ball lands in counts how many times it went right, so the bins fill like the binomial coefficients, which the blue curve shows as they build.

Watch the curve form. Click to drop thirty balls at once.

Technique
A coin flip per peg
Rows
11
Curve
n · C(11, k) / 2¹¹

55Water ripples

Wave equation

drag · click to dropdrag · tap to drop

hₜ₊₁ = ½ Σ neighbours − hₜ₋₁damping 2%

strength slider · refraction 0.12imagedata

A small wave simulation runs on a grid behind the canvas. Every frame, each cell averages its neighbours, and the slope of the surface bends and lights the picture underneath.

Drag through the water, or click to drop a stone. Use the strength slider to calm or stir it.

Technique
2D wave equation, ImageData
Grid
One cell per 2 px, coarser on very large screens
Damping
2% of energy lost per frame

Type & drawing

Letters that move, and tools that draw.

18 specimens

56Proximity type

Variable font

move closerdrag across the words

wght = 200 + 700 · smoothstep(1 − d/r)11 glyphs

variable axis 200 → 900 · ease 18%unbounded

220 px

Each letter is set in a variable font, and its weight follows your pointer. Letters near it swell from hairline to black, while the rest stay thin.

Drag your pointer slowly across the words. Widen the radius to make more letters respond at once.

Technique
Variable font, weight axis 200 → 900
Inputs
Pointer distance to each letter
Falloff
Smoothstep, eased 18% per frame

57Text decoder

Glyph scramble

click for the next wordtap for the next word

glyph = rand(50) until frame ≥ end6 words

start 0–20 f · resolve 10–34 fper-letter timing

Words resolve out of random glyphs, letter by letter, like a terminal cracking a code. Each letter gets its own random start and finish frame, so the word settles unevenly.

Click the stage to jump to the next word.

Technique
requestAnimationFrame, per-letter timing
Glyph set
50 characters
Resolve time
10 to 34 frames per letter

58Velocity marquee

Velocity skew

drag to throw

v = 60 + boost · 0.04ᵗskew ≤ 16°

translateX mod widthseamless wrap

Two endless rows of type drift in opposite directions. Throw them with a drag and they speed up, lean into the motion, and ease back to cruising speed.

Drag sideways across the stage and let go.

Technique
translateX with seamless wrap, skewX from speed
Cruise
60 px/s
Friction
96% of the extra speed gone in 1 s

59Broad-nib pen

Nib sweep

draw · set the nib angle

stroke = sweep(nib, pₜ → pₜ₊₁)16 px nib

width ∝ |sin(heading − angle)|canvas 2d

A calligraphy pen with a flat nib held at a fixed angle. Strokes swell when they cross the nib and thin to a hairline when they run along it, just like ink on paper.

Draw on the stage. Change the nib angle and see how the same gesture changes weight.

Technique
Sweep the nib edge between smoothed points
Nib
16 px at 38°, adjustable
Smoothing
Pen trails the pointer by 65%

60Hanging letters

Pendulums

brush through · click to flickswipe through · tap to flick

α = −(g / L) · sin θ − c·ω5 letters

push ∝ pointer speedcss rotate

A word hung from a rail, one letter per thread. Each letter is a pendulum, so brushing past sets it swinging and longer threads swing slower.

Sweep your pointer through the letters. Click one to flick it.

Technique
Pendulum per letter, CSS rotate
Threads
Staggered lengths, 70 to 128 px
Push
Pointer speed through the glyph

61Split-flap board

Web animations

type a message

top folds 0 → −90° · bottom drops 90 → 0°20 cells

41 characters per drumweb animations

A departures board. Each cell steps through the alphabet one flap at a time: the old top half folds down over the seam, then the new bottom half drops into place.

Type a message and press show. Long ones break across both rows.

Technique
Four half-cards per cell, Web Animations
Board
2 rows × 10 cells
Flap
55 ms per half

62Typewriter

Ink jitter

click the paper, then typetap the paper, then type

ink 72–100% · tilt ±1.6° · baseline ±0.8 px28 columns

bell 4 from the margincourier prime

Type on a sheet of paper. Each key lands with its own ink weight, tilt and baseline like a real type bar, the bell rings near the margin, and the paper rolls up as it fills.

Click the paper and type. Backspace and Enter work too.

Technique
Per-glyph ink, rotation and baseline jitter
Line
28 characters, bell at 24
Face
Courier Prime

63Kaleidoscope

Mirror symmetry

draw · pick a symmetry

for k in N: rotate(2πk / N) · mirror8 slices

2N copies per segmentcanvas 2d

Everything you draw is copied around the centre and mirrored in every other slice, so even a scribble comes out symmetrical. Strokes turn bluer the further they reach.

Draw on the stage. Switch between 6, 8 and 12 segments.

Technique
Rotate and mirror each segment N times
Symmetry
6, 8 or 12 slices
Colour
Ink to blue with distance from centre

64Text on a path

Arc length

draw a line

glyph at s · angle = atan2(dy, dx)1 sentence

binary search on arc lengthcanvas 2d

A sentence flowing along a line you draw. The line is measured by length, so each letter can sit at its own distance along it, turned to the line's direction there. Spacing stays even however the curve bends.

Draw a new line anywhere on the stage.

Technique
Arc-length lookup, rotated to the tangent
Smoothing
Two neighbour-averaging passes
Scroll
46 px a second

65Glyph scatter

Glyph springs

move through · click to scatterdrag through · tap to scatter

F = −k·x − c·v + push7 letters

push ∝ pointer speedcss transforms

Every letter is its own spring. The pointer pushes letters away within a radius, harder the faster it moves, and spins them a little, while each spring pulls its letter home.

Move through the word. Click to blow it apart.

Technique
A spring per glyph, translate and rotate
Reach
110 px
Spring
k 120, c 11

66ASCII render

Luminance ramp

drag to turn · click for a shapedrag to turn · tap for a shape

char = ramp[(n·L + 1) / 2 · 11]3 shapes

z-buffer per cellpre

A spinning 3D shape drawn entirely in characters. Points are sampled over the surface, rotated and projected into character cells; a depth buffer keeps the nearest, and its brightness picks a character from sparse to dense.

Drag to turn it. Click to switch between a torus, a sphere and a knot.

Technique
Depth-buffered points in a text grid
Ramp
12 characters from space to @
Rate
30 frames a second

67Bristle brush

Bristle springs

paint

bᵢ += (target + offsetᵢ − bᵢ)·kᵢ34 bristles

alpha ∝ paint leftcanvas 2d

A brush made of separate bristles, each at its own spot in the head and each trailing your hand on its own spring. Fast strokes splay them, and every bristle runs out of paint at its own rate, so strokes end in dry streaks.

Paint on the stage. Switch between ink and blue, or clear it.

Technique
Bristles on springs, paint load per bristle
Bristles
34
Drying
Load falls with distance painted

68Spray paint

Drip threshold

press to spray · hold still to drip

drip when soak > 726 px patches

run slows e^(−0.9t)canvas 2d

Each frame the can lays down a cloud of fine dots, densest in the middle. The wall keeps a tally of how much paint each patch has taken; past a limit a drip starts there and runs down, slowing as it thins.

Press and spray. Hold still in one spot to make it run.

Technique
Centre-weighted dot cloud, soak tally
Drips
Past 72 dots in a 6 px patch
Run
Slows by e^(−0.9t)

69Elastic headline

Stretch springs

drag a letter up

sx = 1 / √sy7 letters

neighbours × 0.45ⁿ · spring k 260css transforms

Letters stand on a baseline and stretch up from it. Drag one to set its height and its neighbours follow part of the way, so the word bends like rubber. Let go and each springs back through a squat.

Drag any letter up or down.

Technique
Scale from the baseline on springs
Neighbours
Follow by 0.45 per step away
Volume
Width shrinks as height grows

70Text cylinder

rotateY rings

drag to spin and tilt

rotateY(θᵢ) translateZ(r)5 rings

opacity ∝ max(0, cos θ)css 3d

Lines of text wrapped round a turning cylinder in CSS 3D, every letter turned to its angle and pushed out by the radius. Alternate rings turn opposite ways, and letters fade as they face away.

Drag sideways to spin the rings, up and down to tilt them.

Technique
rotateY then translateZ per letter
Rings
5, alternating direction
Fade
By the cosine of each letter's angle

71Signature replay

Recorded timing

sign above the line

dash = length at sample time treal time

svg paths · getTotalLengthsvg

Sign the pad and it plays your signature back exactly as you wrote it. Every pointer sample keeps its timestamp, and the replay reveals each stroke with a dash offset that follows the recorded clock, pauses and flourishes included.

Sign above the line. Pause and it replays; press replay to watch again.

Technique
stroke-dashoffset driven by recorded time
Strokes
Any number, grouped until a pause
Speed
Real time

72Spirograph

Hypotrochoid

click for the next geartap for the next gear

p = (R − r)·e^(iθ) + d·r·e^(−i(R − r)θ/r)6 pairs

closes after r / gcd(R, r) lapscanvas 2d

A gear rolls inside a ring with a pen through one of its holes. The gear's centre circles the ring while it spins backwards, and the pen traces a looping rosette that closes after a whole number of laps.

Watch it draw. Click for the next gear; move the pen hole with the slider.

Technique
Hypotrochoid
Laps
r / gcd(R, r)
Gears
Six ring and gear pairs

73Dot-matrix sign

Bitmap font

type a message

lamp = (row >> (4 − col)) & 15 × 7 font

22 columns a secondcanvas 2d

A scrolling LED sign with a hand-made 5 × 7 bitmap font. Each lamp eases toward on or off, switching on fast and cooling more slowly, so lit dots trail a little behind the scroll.

Type a message and press show.

Technique
Bitmap glyphs, one bit per lamp
Font
5 × 7: A–Z, 0–9 and punctuation
Lamps
On in about 25 ms, off in about 110 ms

Interface

Small interactions that make controls feel physical.

17 specimens

74Magnetic buttons

Spring offset

approach a buttondrag near a button

shift = 12 px · smoothstep(1 − edge / 80)4 buttons

spring k 300 · c 26 · label +40%never touch

Buttons lean toward your pointer when it comes close, and their labels lean a little further, which gives each one a sense of depth. A spring pulls them home when you move away.

Move your pointer near any button, then away.

Technique
Custom properties driven by a spring
Reach
80 px past the button edge, at most 12 px of travel
Label shift
40% of the button's shift

75Scroll-driven cards

Scroll timeline

scroll inside

progress = view(cover 0% → 100%)0 lines of js

in to 28% · hold · out from 72%@supports fallback

Cards rise into place as they scroll into view, and a bar tracks how far you've read. It's all CSS with no JavaScript, using scroll-driven animations.

Scroll inside the stage.

Technique
animation-timeline: view() and scroll()
JavaScript
None
Support
Chromium and Safari 26+; elsewhere the cards appear without motion

76Card to detail morph

View transitions

open a card

startViewTransition(update)2 shared

plate · title · 450 msview transitions

Click a plate and its pattern and title glide into the detail view as one continuous shape. The browser snapshots both states and animates between them.

Open a card, then go back.

Technique
document.startViewTransition()
Shared elements
Pattern plate and title
Fallback
Instant swap where unsupported

77Rolling odometer

Digit strips

press the buttons

yᵢ = −digitᵢ · 1.1em7 digits

stagger 60 ms · overshoot 1.3css transitions

Each digit is a strip of numbers behind a window. Changing the value slides every strip to its new digit with a little overshoot, the leftmost digits arriving last.

Press the buttons to add to the count.

Technique
translateY on digit strips, CSS transitions
Digits
7, leading zeros dimmed
Stagger
60 ms per digit

78Rubber-band list

Overscroll

fling · pull past the end

shown = (1 − 1 / (0.55·d / h + 1)) · hevery specimen

friction e^(−3.2t) · spring k 180momentum

A list with real momentum. Fling it and it coasts; pull past either end and it resists more and more, then springs back when you let go.

Drag or fling the list, or use the wheel or arrow keys. Pull past the ends.

Technique
Momentum, rubber-band overscroll, spring return
Friction
e^(−3.2t)
Return
Spring k 180, c 26

79Toggle personalities

Role = switch

flip each switch

spring · squash · liquid · flip4 switches

role=switch · aria-checkedkeyboard ready

Four switches with the same job and different characters. One bounces, one stretches with speed, one pours its colour out of the knob, and one turns over like a coin.

Click each switch, or tab to them and press space.

Technique
Springs driving CSS custom properties
Semantics
Real buttons with role switch
Springs
k 220 to 420 per personality

80Picker wheel

Momentum snap

drag or scroll a wheeldrag a wheel

angle = row·20° · snap to round(pos + v·0.12)2 wheels

spring k 160 · c 20css 3d

A time picker built as two drums in CSS 3D. Each row sits at its own angle round the drum, so turning the drum is a single number. A flick coasts on its own speed, then a spring settles it on the nearest row.

Drag or scroll a wheel, or focus it and use the arrow keys.

Technique
rotateX drum, momentum, snap
Rows
20° apart, recycled
Semantics
role spinbutton with value text

81Swipe stack

Fling threshold

drag a card sideways

throw if |x| > w/3 or |v| > 900endless deck

lean = x · 0.06°css transforms

A deck of cards you sort with a flick. The top card follows your finger and leans as it goes; past a third of its width, or with enough speed, it flies off and the next card rises into place.

Drag a card left or right, or use the buttons or arrow keys.

Technique
Distance or speed threshold
Threshold
A third of the width, or 900 px/s
Return
Spring k 170, c 20

82Sortable list

Spring slots

drag a handle

slot = round(y / 42)6 rows

spring k 260 · c 26css transforms

Drag a row by its handle and the others glide out of the way. Every row has a spring toward its slot; the held row follows the pointer exactly and the order updates from where its centre is.

Drag a handle. Or focus a row, press space to lift it, and use the arrow keys.

Technique
A spring per row toward its slot
Keyboard
Space lifts and drops, arrows move
Announcements
Live region on every move

83Bottom sheet

Detent snapping

drag the sheet

snap = nearest(y + v·0.2)3 detents

rubber band past the endscss transforms

A sheet with three resting heights. Dragging moves it one to one, with resistance past the ends. On release it projects where its speed would carry it and snaps to the nearest height, so a flick goes further than a slow drag.

Drag the sheet and let go. Tap the handle, or use it from the keyboard, to step through the heights.

Technique
Velocity projection to detents
Detents
Peek, half, full
Projection
Position plus 0.2 s of speed

84Hold to confirm

Press and hold

press and hold

p += dt / 1 s while held1 s hold

drains 3× · label clipped twicecss clip-path

A destructive button you have to hold. Progress fills only while it's held and drains faster if you let go early, so a slip is easy to undo. The label is drawn twice, one copy clipped to the fill, so it stays readable across the edge.

Press and hold the button, or hold Space or Enter on it.

Technique
Clip-path fill, doubled label
Hold
1 second
Release
Drains 3 times faster than it fills

85Sliding tabs

Two-edge springs

pick a tabtap a tab

lead k 420 · trail k 1204 tabs

role=tablist · roving tabindexkeyboard ready

Tabs with two indicators. The pill glides as one shape on a spring. The underline has a spring on each end: the leading end is stiff and leaves first, the trailing end is soft and catches up, so the line stretches mid-move.

Click a tab, or use the arrow keys inside the tab list.

Technique
A separate spring for each edge
Leading edge
k 420, c 34
Trailing edge
k 120, c 18

86Toast stack

Stacked layout

notify · hover the pilenotify · tap the pile

collapsed: y = −12i · s = 1 − 0.05i5 at most

timers pause while opencss transforms

Notifications that pile up neatly. Older toasts tuck behind the newest, each a little higher and smaller; hovering or focusing the pile fans it into a list and pauses the timers. Swipe a toast sideways to dismiss it.

Press notify. Hover the pile to open it, then swipe or close a toast.

Technique
Spring stack, collapsed and open layouts
Life
5.2 s, paused while open
Limit
5 toasts

87Morphing pill

Size morph

click to change statetap to change state

w, h, radius on springs4 faces

fade in after 55% of the morphcss transforms

One container with four faces: a clock, a timer, music and a player. Width, height and corner radius ride springs toward the next face's size, and the new face waits until the shape is mostly there, so content never squeezes.

Click the pill to change its state.

Technique
Size springs, staged cross-fade
States
Clock, timer, music, player
Spring
k 260, c 21

88Like burst

Particle burst

click the hearttap the heart

scale 0.6 → spring k 420 · c 1414 dots

ring and dots · 650 mscanvas + svg

Liking plays three things at once: the heart squashes and springs past its size, a thin ring flashes outward, and a dozen dots fly out on two radii. The count rolls up a line instead of swapping in place.

Click the heart, then click again to unlike.

Technique
Spring scale, canvas particles
Burst
A ring and 14 dots over 650 ms
Semantics
aria-pressed toggle

89Elastic slider

Rubber band

drag past an end

over = 40·(1 − 1/(d/60 + 1))0 to 100

scaleX(1 + over/w)role slider

A volume slider that stretches. Inside the range it tracks the finger exactly; pulled past an end it keeps following with growing resistance, the bar stretching and thinning like a strap, and the icon at that end swells to match.

Drag past either end and let go. The arrow keys bump against the limits too.

Technique
Rubber-band overflow, return spring
Give
Up to 40 px, compressed
Return
Spring k 300, c 16

90Spring shuffle grid

FLIP

sort · click a tilesort · tap a tile

first → last → invert → play24 tiles

spring k 170 · c 16 · stagger 12 mssettles —

The tiles really change places in the page layout. Each one remembers where it was, jumps to its new spot, then springs back across the gap so the move looks continuous. This trick is called FLIP.

Shuffle or sort the tiles, or click any tile to send it to the front.

Technique
FLIP with the Web Animations API
Easing
Spring baked into CSS linear()
Spring
Stiffness 170, damping 16
Stagger
12 ms per tile