SVG✨ Premium

Cellular Automata

Conway's Game of Life on a grid of small coloured cells: ten generations per second, cycling hues, and a new population every 50 seconds.

CanvasSimulationConway

Updated

This effect is part of Effect.Labs — 840 vanilla effects, some free, some premium. SVG has 30 effects, including 3 free. Explore the category →

3 usage examples

Registration page background for an artificial life conference — Cellular Automata example 1

① Registration page background for an artificial life conference

WhenOn the Abiotelle 2027 page, the automaton covers the whole screen, dimmed; title, dates and topics on the left, the registration form in an opaque card on the right.
WhyThe Game of Life is the founding example of artificial life: the background states the conference topic, and its patterns being born and dying stay fine enough to sit behind a form.
SettingsRoot in position:absolute; inset:0 with --gol-height:100% and opacity:.7; radial veil centred on the text; canvas set to aria-hidden="true". A 90 × 60 cell grid on 540 × 360 px.
Animated thumbnail for a course in a training catalogue — Cellular Automata example 2

② Animated thumbnail for a course in a training catalogue

WhenIn the Codalme catalogue, the "Cellular automata" course card uses the running automaton as its image, next to two courses with still thumbnails.
WhyThe thumbnail shows the course topic instead of illustrating it, and the motion flags the new course in a grid of static cards.
SettingsRoot inside a 157 × 112 px thumbnail (26 × 18 cells), with a "New" badge on top. The canvas keeps role="img" and a label because it replaces the card image.
Waiting area while a moving quote is computed — Cellular Automata example 3

③ Waiting area while a moving quote is computed

WhenOn the Démorvel simulator, clicking "Get my quote" swaps the welcome message for the automaton and "Calculating your quote…", then the amount shows up a few seconds later.
WhyA population that evolves without ever repeating keeps the eye busy without promising a numeric progress, which a made-up loading bar would wrongly do.
SettingsThe waiting area (250 × 150 px, 41 × 25 cells) is only displayed in the "waiting" state; the sold code starts the first time it appears, stops when it disappears and resumes the same population on the next calculation.

How it works

The area is split into 6 px cells (centred grid), 30 % of which are drawn alive at the start. On each generation every cell counts its eight neighbours: a live cell survives with 2 or 3, a dead cell is born with exactly 3, every other cell dies or stays empty. The new grid is computed entirely from the old one, and edges wrap around like a torus: whatever leaves on the right comes back on the left.

A generation lasts 100 ms, measured in elapsed time (capped at 50 ms per frame), i.e. ten per second on any screen. The canvas is only redrawn when the generation changes: each live cell becomes a 4 px square with a 2 px gap, coloured hsl(generation × 2 + row + column, 70 %, 55 %), which produces rainbow diagonals that slide over time. After 500 generations (50 s) a new random population starts, because a random soup ends up as still blocks and blinkers.

Grid size comes from the displayed area (multiplied by devicePixelRatio for crisp rendering); a ResizeObserver restarts a fitting population when the area changes size, and nothing starts while it is smaller than one cell. An IntersectionObserver stops computing off screen. The canvas is transparent: the background is that of .fx-0618-root. Every root has its own population, started only once (data-gol-ready) even if the script is pasted twice.

Accessibility

  • Label: role="img" and aria-label on the canvas. As a page background, or in a waiting area already described by text, switch it to aria-hidden="true".
  • Reduced motion: under prefers-reduced-motion: reduce, 40 generations are computed in one go and the grid is shown frozen, with its first stable structures.
  • Flicker: the most common oscillators switch state on every generation, i.e. 5 back-and-forths per second, on 4 px squares. For flicker-sensitive audiences, raise GENERATION_MS to 350 to stay under 3 changes per second.
  • Pausing: no built-in button; toggling the root's hidden attribute stops the computation (WCAG 2.2.2) and resumes it at the same generation.
  • Keyboard: no interactive element in the effect.

Browser compatibility

2D canvas and about 4.3 KB of JavaScript, no dependency. ResizeObserver: Chrome 64, Firefox 69, Safari 13.1; IntersectionObserver: Chrome 51, Firefox 55, Safari 12.1 (MDN data). Measured in Chromium 151, Firefox 153 and WebKit 26.5: 2× density rendering, two independent populations, start after a delayed reveal, frozen grid under reduced motion, no computation off screen.

Chrome 64+✓ Full (measured)
Firefox 69+✓ Full (measured)
Safari 13.1+✓ Full (measured in WebKit)
Edge 79+✓ Full (Chromium engine)
Safari iOS 13.4+✓ Full (WebKit, not checked on a device)
Chrome Android 64+✓ Full (Chromium engine)

Without ResizeObserver, the grid only adapts on window resize; without IntersectionObserver, generations keep running off screen. Without JavaScript, the area keeps the root's background.

The code

HTML structure to paste into your page (the CSS + JS come with your purchase):

index.html — structure
<div class="fx-0618-root">
  <canvas class="gol-canvas" role="img" aria-label="Conway's Game of Life: coloured cells being born and dying on a grid"></canvas>
</div>

One-time payment, no subscription — the code is yours forever

Customize

Options passed to the API or data-* attributes:

Option / propertyDefaultEffect
Cell size (JS — CELL) 6 px (4 px squares) 4 px gives a fine texture, 10 px readable patterns where gliders and blinkers can be recognised.
Starting population (JS — DENSITY) 0.3 0.15 leaves a few islands that die out fast, 0.5 a scramble that thins out before organising itself.
Generation length (JS — GENERATION_MS) 100 ms 350 ms or more for a calm pace and fewer than 3 blinks per second, 50 ms for fast evolution.
Renewal (JS — RESTART_AFTER) 500 generations Infinity lets the population die out or freeze on its own; 200 restarts a busy soup more often.
Colours (JS — fillStyle line in draw()) hsl(generation × 2 + row + column, 70 %, 55 %) A fixed hue such as 'hsl(170, 70%, 55%)' gives a sober single-colour grid.
Background (CSS — background of .fx-0618-root) #0a0a0f The canvas is transparent: this colour is the only one that matters, light backgrounds included.
Height (CSS — --gol-height) 300px Any fixed height, or 100% inside a parent of known height.

FAQ

Yes: rule B3/S23 (birth with 3 neighbours, survival with 2 or 3), synchronous update of the whole grid and an eight-cell Moore neighbourhood. The one twist is that edges wrap: a glider leaving one side comes back on the other.
Not with the provided settings: seed() draws cells at random. For a pattern, replace that draw with the list of cells to switch on (row, column) inside seed(), and set RESTART_AFTER to Infinity so it is not wiped.
A random population settles within a few hundred generations: only still blocks and blinkers remain and the picture becomes repetitive. RESTART_AFTER (500 generations at 10 per second) starts a fresh soup before that happens.