A five-step recipe

Start from a grid

Build a finished geometric pattern from one grid. Each step adds one idea—structure, position, rhythm, variation, then selection—so you can see exactly what changes the result.

Finished pattern Click to regenerate

01 Structure

Make the grid visible

@grid creates a 7 × 7 grid and makes the doodle 60vmin square. The value after the second slash paints the canvas behind the cells. The _ 2px modifier adds a small gap, and regular CSS gives every cell a light background. One number makes a square; two numbers, such as 4x8, set columns and rows.

@grid: 7 / 60vmin / #333 _ 2px;
background: #fff;

02 Position

Let each cell know where it is

css-doodle evaluates every declaration once per cell. @i is the cell index, starting at 1 in the top-left and moving across each row. Multiplying it by 7 turns that sequence into a hue, so position now controls color.

@grid: 7 / 60vmin / #333 _ 2px;

/* 7°, 14°, 21° … one hue per cell */
background: hsl(@i(*7), 78%, 62%);
@content: @i;
color: #fff;

03 Rhythm

Repeat a sequence of shapes

@p.cycle(100% 0 0 0) takes the four rotations of one corner radius and picks one for each cell. The squares become quarter-circles that face different ways.

@grid: 7 / 60vmin / #333 _ 2px;
background: hsl(@i(*7), 78%, 62%);
border-radius: @p.cycle(100% 0 0 0);

04 Variation

Make randomness intentional

Replace the hue formula with a small palette, then let each cell choose a color and rotation. @r(.82, 1) gives every cell a scale within that range. The choices vary, but the limited palette and quarter-turns keep the composition coherent.

@grid: 7 / 60vmin / #333 _ 2px;

background: @p(#ff5f57, #ff9f1c, #7657ff);
border-radius: @p.cycle(100% 0 0 0);
rotate: @p(0deg, 90deg, 180deg, 270deg);
scale: @r(.82, 1);

05 Selection

Direct attention with cell selectors

A @cell block applies only where its expression matches. x = y is one diagonal. On a 7 × 7 grid, x + y = 8 is the other. Those cells become full-size circles, so the two diagonals read as an X.

@grid: 7 / 60vmin / #333 _ 2px;

background: @p(#ff5f57, #ff9f1c, #7657ff);
border-radius: @p.cycle(100% 0 0 0);
rotate: @p(0deg, 90deg, 180deg, 270deg);
scale: @r(.82, 1);

@cell(x = y, x + y = 8) {
  border-radius: 50%;
}

Pattern complete

Five ideas, one reusable process

Start with structure, derive values from position, establish a sequence, constrain randomness, then select a few cells for emphasis. Swap the palette, grid size, or shape sequence and the same process produces a completely different piece.

Remix it in the playground

Where to go next