🟧 Albers’ Squares

Homage to the Square, generated

Generating designs in the style of Josef Albers’ Homage to the Square — nested, offset squares in a random gradient, a new composition every few seconds, finished with a soft grain. Built in p5.js, first as a 2021 experiment.

Readme

A p5.js sketch that generates designs in the style of Josef Albers' Homage to the Square: nested, offset squares filled with a random gradient, a new composition every few seconds, finished with a soft grain.

From a 2021 experiment, rebuilt as a self-contained static page.

Run it

Open index.html in a browser, or serve the folder:

python3 -m http.server

p5 loads from a CDN; everything else is in sketch.js.

What's here

  • index.html — the page: loads p5 and the sketch, and starts it.
  • sketch.js — the sketch. setColors builds the palette, createSquares stacks the nested squares, and a generated grain is soft-light blended on top. The original overlaid a canvas.jpg texture that was lost; the grain stands in for it.

One copy of the sketch

sketch.js does not start itself. It puts an instance-mode factory on window.albersSketch and stops there, so the page that loads it decides when to run it and keeps the handle to stop it again:

const instance = new p5(window.albersSketch, document.getElementById('albers-container'));

That is what index.html does here, and it is what the Albers post on bobbymeyer.com does too — it loads this same file from this deploy rather than keeping a copy of its own, and tears its instance down when the site's client router navigates away. The post used to carry a second copy, and the two drifted the first time the palette changed. Anything that would break that call — renaming the global, starting the sketch from this file, needing a p5 the post does not load — breaks the post, so it is worth a thought before changing.

About the palette

The first version lerped between two independently random RGB colours, which regularly landed two touching squares close enough to merge — a four-square composition would read as two or three. The palette is now built in OKLab, where a step in lightness is roughly a step in what the eye sees, so neighbouring squares can be held at least MIN_STEP apart in lightness. L_FLOOR and L_CEIL keep the ramp off the ends where a screen crushes everything to black or white, and only chroma is ever trimmed to fit sRGB — which leaves those lightness gaps intact on the canvas. A composition can still come out dark, pale or near-grey; it just cannot come out with fewer squares than it has.

MIN_SQUARES and MAX_SQUARES set how many squares a composition stacks — 3 to 5, picked evenly.