Skip to content

PRIMITIVE

Collage

Rows of unequal tiles, with a gutter, and no breakpoint anywhere. Reach for it when a wall of things should be looked at rather than scanned — a mark, a clip, a picture and a stack of links, arranged so the eye moves.

The rhythm

Three rows: a third and two thirds, then a quarter, a half and a quarter, then two thirds and a third. Narrow the window and each row holds its proportions until it wraps.

1 of 3
DOUBLE 2 of 3
1 of 4
DOUBLE 2 of 4
1 of 4
DOUBLE 2 of 3
1 of 3
HTML
<!-- The three-row rhythm: 1/3 2/3 · 1/4 1/2 1/4 · 2/3 1/3. Every wide tile is
     the same `collage-tile-double`; the fractions come from the row it is in. -->
<div class="collage" style="--collage-min:90px; width:100%">
  <div class="collage-row">
    <div class="collage-tile">
      <div class="placeholder" style="--ratio:1/1">
        <span class="placeholder-note">1 of 3</span>
      </div>
    </div>
    <div class="collage-tile collage-tile-double">
      <div class="placeholder placeholder-warm" style="--ratio:2/1">
        <span class="placeholder-kicker">DOUBLE</span>
        <span class="placeholder-note">2 of 3</span>
      </div>
    </div>
  </div>

  <div class="collage-row">
    <div class="collage-tile">
      <div class="placeholder" style="--ratio:1/1">
        <span class="placeholder-note">1 of 4</span>
      </div>
    </div>
    <div class="collage-tile collage-tile-double">
      <div class="placeholder placeholder-warm" style="--ratio:2/1">
        <span class="placeholder-kicker">DOUBLE</span>
        <span class="placeholder-note">2 of 4</span>
      </div>
    </div>
    <div class="collage-tile">
      <div class="placeholder" style="--ratio:1/1">
        <span class="placeholder-note">1 of 4</span>
      </div>
    </div>
  </div>

  <div class="collage-row">
    <div class="collage-tile collage-tile-double">
      <div class="placeholder placeholder-warm" style="--ratio:2/1">
        <span class="placeholder-kicker">DOUBLE</span>
        <span class="placeholder-note">2 of 3</span>
      </div>
    </div>
    <div class="collage-tile">
      <div class="placeholder" style="--ratio:1/1">
        <span class="placeholder-note">1 of 3</span>
      </div>
    </div>
  </div>
</div>

A tile holds anything

The collage arranges and draws nothing. A plate, a rule stack, a paragraph — it has no opinion about what is inside a tile, which is what separates it from a grid of cards.

PLACEHOLDER A clip, or a picture
LINUX x86_64
MACOS arm64
WINDOWS x86_64

A tile can be a paragraph. Nothing here frames it, so it sits on the page ground with the gutter around it.

Bleed — 21:9
HTML
<!-- A tile holds whatever you put in it. The collage arranges; it draws nothing
     and it has no opinion about what a tile contains. -->
<div class="collage" style="--collage-min:100px; width:100%">
  <div class="collage-row">
    <div class="collage-tile collage-tile-double">
      <div class="placeholder placeholder-warm" style="--ratio:16/9">
        <span class="placeholder-kicker">PLACEHOLDER</span>
        <span class="placeholder-note">A clip, or a picture</span>
      </div>
    </div>
    <div class="collage-tile">
      <div class="rule-stack">
        <div class="rule-row rule-row-spec">
          <span class="rule-row-key">LINUX</span>
          <span class="rule-row-value">x86_64</span>
        </div>
        <div class="rule-row rule-row-spec">
          <span class="rule-row-key">MACOS</span>
          <span class="rule-row-value">arm64</span>
        </div>
        <div class="rule-row rule-row-spec">
          <span class="rule-row-key">WINDOWS</span>
          <span class="rule-row-value">x86_64</span>
        </div>
      </div>
    </div>
  </div>

  <div class="collage-row">
    <div class="collage-tile">
      <p class="placeholder-caption">A tile can be a paragraph. Nothing here frames it, so it sits on the page ground with the gutter around it.</p>
    </div>
    <div class="collage-tile collage-tile-double">
      <div class="placeholder" style="--ratio:21/9">
        <span class="placeholder-note">Bleed — 21:9</span>
      </div>
    </div>
  </div>
</div>

Reference

Read from primitives/collage.css when this page was built, so it cannot fall behind the stylesheet.

CLASSES.collage.collage-row.collage-tile.collage-tile-double
SETTINGSSet the first on one element; a theme sets the second for all of them.--collage-gap — falls back to --ds-collage-gap--collage-min — falls back to --ds-collage-min
READSNothing from the theme — it is arrangement only.

Notes

🛑 THE WEIGHT IS RELATIVE TO ITS ROW, SO IT IS NOT NAMED AS A FRACTION

Look at the first specimen again. Every wide tile in it is the same collage-tile-double — and the first one is two thirds of its row while the second is a half of its own. Nothing changed but the number of tiles beside it.

That is why there is no collage-third. A class with a fraction in its name would be telling the truth in one row and lying in the next, and you would have to count the siblings to know which. Weights are what a row actually divides by, so weights are what the vocabulary says.

TWO WEIGHTS, AND A THIRD WHEN SOMETHING ASKS

One and two. Between them they spell every row above, and every row in the sketch this was built from. A weight of three is one line of CSS the day a composition needs it — and until then it is a ratio nobody has asked for, which is a ratio that will be wrong when somebody finally does.

THE FLOOR IS PER WEIGHT, AND THAT IS WHAT KEEPS THE RATIO EXACT

One floor for every tile is the obvious spelling, and it distorts a row before it breaks it. At the width where a plain tile lands on a shared 300px minimum, its double neighbour is still growing — so 1:2 quietly becomes about 1:1.3 for a couple of hundred pixels, and nothing tells you.

So --collage-min is the floor of one weight, and a double tile floors at twice it. The tiles reach bottom together, the proportions hold right up to the moment the row wraps, and one number states the whole relationship.

THE BASIS IS ZERO AND THE GROW CARRIES EVERYTHING

Split puts its ratio in percentage bases, which works because it knows it has one gutter to leave room for. A collage does not: a row has as many gutters as it has tiles, minus one. Author the bases under 100% for two tiles and the three-tile row overflows and wraps when it should not.

A zero basis sidesteps the whole question. The row is entirely free space, gap comes out of it first, and the grow ratio divides what is left — exact at every width, at any number of tiles, with any gutter.

IT WRAPS GREEDILY, LIKE A SPLIT

A row of three passes through a two-then-one stage on its way down rather than stacking all at once. That is flex line-breaking, not a defect — a line takes as many tiles as their floors allow. Worth knowing before you count on three going straight to a column of three.

THE GUTTER IS vw, NOT cqi

Deliberate, and the reason is a good trap. .collage is itself a container, and an element cannot read its own container units — so cqi on the row gap would measure this box while the same expression on the column gap measured whatever box is outside it. Two different gutters at right angles, in a device whose whole job is one even mesh.

IT PAINTS NOTHING

No border, no ground, no radius. A tile that should look like a card puts a frame or a clip inside it. A collage that drew its own boxes would be a hairline grid with the lines rubbed out — and if that is what you want, that is the one to reach for.