Flat fields of ultramarine, orange, viridian and pink slide in along razor edges and change proportion, ending in a quarter-disc composition, while one small warm-grey square never moves or changes yet seems to shift color with every new surround.
Written and rendered by AI CSS Animations Oct 18, 2026
Hard-edge painting is a name the Los Angeles critic Jules Langsner gave in the late 1950s to the work of painters such as Karl Benjamin, Frederick Hammersley, Lorser Feitelson and John McLaughlin. In place of gestural brushwork they used large areas of flat, evenly applied color meeting along clean, sharp edges, so the relationships between colors and shapes became the subject, and Ellsworth Kelly pursued similar ideas in New York. Josef Albers's Homage to the Square series, begun in 1950, showed how one color seems to change with what surrounds it. The look runs through brand identities, book covers and editorial illustration today.
Make a 10-second hard-edge abstraction: large flat fields of color with razor edges slide, change proportion and trade places, while one small square that never changes seems to change color with them. <inputs> Title: Edge Conditions. Line: Paintings in flat color. Details: Gallery 5 · 2 March to 26 May. Closing note: "The square never changes." Duration: 10s. If I don't give you something, use the default and don't ask. </inputs> <direction> Palette, flat acrylic: ultramarine #1F2D9C, cadmium orange #F25A1F, viridian #0E6450, pink #F2A3B3, black #161616, cream #F1E9D6. The square is #9C8B6E, a warm grey-ochre that reads warm on blue and cool on orange. At most five colors on screen at once, the square included. The canvas is the whole stage. A faint static linen weave (a seeded fine crosshatch at 2%, multiplied) makes it read as paint on canvas; nothing else breaks the fields. Edges are the subject: every boundary is a perfectly straight line or one large circular arc. Fields overlap rather than butt, each new field drawn over the one it replaces, so there is never a hairline seam or a gap. Corners are sharp. The square: 220×220 at x 1260–1480, y 430–650 for the whole piece, always on top, never moving, never changing. Compositions, in stage pixels: - Start: ultramarine fills the canvas; the square sits on blue. - A: orange fills x 1200–1920. The square sits on orange. - B: the blue–orange edge moves left to x 720, and a viridian field rises from the bottom to y 760 across x 0–720. - C: a pink field sweeps in from the right edge to x 1100, so the square sits on pink; orange remains as a band at x 720–1100. - D: ultramarine widens to x 1040 and the viridian sinks out of the bottom; the pink widens left to x 1120; a black band drops over x 1040–1120. Blue, black, pink: a still triptych. - Final: an orange quarter-disc grows from the lower right corner, centered at (1920, 1080), to radius 770, its arc passing through the square's center, so the square sits half on pink and half on orange: the plainest proof that it doesn't change. Type, set quietly into the final painting in "Instrument Sans": the title in 600, 44px, cream, from (120, 940); the line and details in 400, 22px, cream at 80%, beneath it at baselines 980 and 1010; the closing note in 500 italic, 26px, black, on the pink at (1200, 140). Motion is deliberate: edges travel on cubic-bezier(0.76, 0, 0.24, 1) over 0.4–1.0s, one or two at a time in counterpoint, and every change of color arrives as a new field sliding in along its edge, never as a fade. The arc grows by its radius from the corner. Each composition holds at least 0.4s so it can be looked at. The real thing is proportion, interval and two colors pressing on each other along a perfect edge; the cheap version is a random rectangle shuffle with gradients and drop shadows. Banned: gradients, crossfades or opacity changes on color fields, outlines, drop shadows, rounded corners, texture beyond the 2% weave, more than five colors on screen, seams or gaps between fields, the square moving or changing, edges that are neither straight nor a single arc, anything flashing more than 3 times per second. </direction> <structure> 0.0–0.5s: ultramarine and the square, still. 0.5–1.4s: A: the orange field slides in from the right edge to x 1200. 1.4–2.0s: hold A. 2.0–3.0s: B: the blue–orange edge slides left to x 720 while the viridian rises from the bottom. 3.0–3.6s: hold B. 3.6–4.5s: C: the pink sweeps in from the right to x 1100. 4.5–5.0s: hold C. 5.0–5.5s: D begins: the orange's left edge slides right to x 1040, widening the blue, as the viridian sinks out of the bottom and the pink edge moves to x 1120. 5.5–5.9s: the black band drops from the top over x 1040–1120. 5.9–6.3s: hold D. 6.3–7.3s: the orange quarter-disc grows from the lower right corner to its full radius. 7.3–8.1s: the title, then the line and details, then the closing note appear, each rising 8px out of a mask at its baseline. 8.1–10.0s: hold, completely still. For other durations, scale the holds first and keep each edge move between 0.4 and 1.2s. </structure> <build> One self-contained index.html, CSS and JS inline. Google Fonts via <link> are fine; no other libraries (no three.js: this style is flat). Draw in inline SVG with shape-rendering="geometricPrecision": fields are rects and paths whose edge coordinates and arc radius are set from seek, ordered so each new field overlaps the one it replaces by at least 2px. Generate the linen weave once at load into a canvas laid over the SVG with mix-blend-mode: multiply. Await document.fonts.load() for each face, then define window.seek. The stage is 1920×1080 (16:9), scaled to fit the window. Design for 60fps. window.seek(t), t in seconds, must compute every visual from t alone: no CSS transitions or animations, no setTimeout or setInterval, no state carried between frames, and randomness only from a seeded PRNG. Anything cumulative is precomputed once at load at a fixed step or solved analytically from t, so any frame can be drawn directly. Without ?render in the URL, drive seek from requestAnimationFrame so it plays in a browser (loop after a 1s end hold); with ?render, don't start that loop. </build> <check> Before showing me, step through one frame per second: screenshot each and look at it. Fix overlaps, clipped or cramped text, accidental edge collisions, and anything off-style or Banned. Sample the square's pixels on every frame: its color must be identical throughout. Check there are no seams or slivers of the wrong color along any edge at 1280×720, no frame shows more than five colors, each hold frame is a balanced composition on its own, and the type sits clear of every edge it shares a field with. Confirm seek(duration) and seek(duration + 1) match, so the final frame holds. </check>
Ours, and free to use under CC0: copy it, change it, ship it. No credit needed.
A jazz-tempo film title sequence in flat vermilion, mustard, bone and black: hand-cut paper shards jab in on the beat,…
A Swiss-style event poster that builds itself on a visible 12-column grid: grotesque type rises out of baseline masks,…
A primary-colored circle, square and triangle roll, drop and turn into place on a black bar, assembling a constructed B…
A Constructivist poster in motion: red bars, a wedge piercing a black circle, halftone fields and condensed uppercase t…
More like this on the motion design inspiration board: Motion graphics inspiration