Theme
Design your own
On this page (6)

§Pattern Lab

Pick a backend, then a pattern, a material, a projection and a motion; the preview and its markup follow. The arrows beside a list step through it and start over at its end. Light and elevation place the light (the CSS backend turns them into the direction and the width of its rims and shadows), speed sets the pace (0 stands still), direction where a drift runs and rotation turns the pattern in its plane. The CSS backend offers the Surface's 28 tiles, 25 styles, 22 projections and 23 motions; the shader backend the surface effect's 26 patterns, 28 materials, 13 projections and 24 motions. "Surprise me" draws a random combination.

§Every combination

Change a control - the surface and its markup change with it. The arrows beside a list step through it and start over at its end. Move the pointer over a shader surface to move its light.

§Four words

A pattern says what repeats, a material how it is lit, a projection on which plane it lies and a motion how it moves. Each is a data-* attribute, so a surface is plain markup an agent can write and a person can read. The words are the same in both backends where both can draw them; the shader adds what needs light and depth per pixel.

flowchart LR
    P["pattern<br/>hex, bricks, circuit ..."] --> S(("surface"))
    M["material<br/>flat, emboss, neon, glass, gold ..."] --> S
    J["projection<br/>flat, floor, wall, tunnel, dome ..."] --> S
    O["motion<br/>drift, orbit, rain, glitch ..."] --> S
    S --> C["CSS: .surface<br/>masks and transforms"]
    S --> G["GPU: .shader data-effect=surface<br/>one fragment pass"]
Fig 1. A surface is four independent choices, drawn by CSS or by the GPU.
the two backends
CSS - .surfaceGPU - .shader data-effect="surface"
Patterns28 tiles (SVG and gradient masks)26 procedural patterns
Materials25 styles - emboss, shadows, extrusions, neon, glass, metal, gold, stamp, chalk, blueprint, risograph ...28 materials lit per pixel - bevel, ceramic, chrome, glass, wood, marble, ice, lava, gem, pearl, toon, x-ray ...
Projections22 - floors, ceilings, walls, tilts, corridor, horizon, isometric, dimetric, cavalier, cabinet ...13 - floor, ceiling, wall, hallway, corridor, tunnel, column, dome, sphere, cube, isometric ...
Motion23 - drift, orbit, rotate, sway, swing, wave, bounce, glitch, breathe, heartbeat, hue ...24 - drift, ripple, warp, mutate, zoom, spiral, swirl, rain, cascade, flip, spin, sparkle, scan ...
Light--surface-light-angle: rims and shadows fall away from itdata-light + data-elevation, or the pointer
Direction and rotation--surface-direction, --surface-rotationdata-direction, data-rotation
Costa paint when still; a motion moves a transform - no repaintone fragment pass per frame while in view; the far plane is only its average
Without scriptrendersthe CSS poster
Bundleall.cssshaders.css + shaders.js

§Seamless by construction

A seam appears where a tile's right edge does not continue its left edge. The CSS tiles are drawn so that every shape crossing an edge is drawn again on the opposite side, and the noise tiles use stitchTiles="stitch". The shader never repeats a tile at all: it evaluates the pattern at every point of an endless plane with fract() and integer cell ids. Where the plane wraps around a tunnel or a ball, the cell ids are taken modulo the number of tiles around it and the noise uses a lattice with the same period, so the last tile meets the first. Motions loop by whole tiles or return to where they started.

§Mutation, subtle by default

Four kinds of change, from quiet to loud. Cosmetic: data-variation (0.15) jitters each cell's lightness and the share of second-color cells. Geometric: pulse and warp move the edges. Structural: mutate re-rolls cells one by one - truchet arcs turn, maze walls flip, circuit traces rewire, and because an edge belongs to both cells it joins, traces always meet. Interactive: with data-interactive the pointer moves the light and centers the ripple.

§Performance

CSS first: a still Surface costs a paint and nothing after; a moving one moves a transform, an opacity or a filter, which the compositor runs without repainting (a drift on a receding plane and shimmer repaint per frame). Shaders draw only near the viewport, stop when the tab hides and hold one still frame under reduced motion; data-quality="low" renders at half a pixel per CSS pixel, the default caps the device pixel ratio at 1.5 and a pixel budget, and late frames lower the resolution further. data-fps="30" halves the work of a quiet background. Without WebGL2 a shader shows its CSS poster - for a surface, a Surface behind it is a good fallback.

Comments, ideas or improvements? Edit this page's source on GitHub