PRIMITIVE
Cluster
A row of things that wraps, with one gap between all of them. Two buttons, a row of chips, a legend, a byline beside a date.
Three of them, and one with a wider gap
<div class="flow" style="width:100%">
<div class="cluster">
<a class="btn btn-primary" href="#">RÉSUMÉ ONLINE</a>
<a class="btn btn-quiet" href="#">RÉSUMÉ PDF</a>
</div>
<div class="cluster">
<span class="chip">PHP</span>
<span class="chip">LARAVEL</span>
<span class="chip">TYPESCRIPT</span>
<span class="chip">TAILWIND</span>
<span class="chip">ALPINE</span>
</div>
<div class="cluster" style="--cluster-gap: var(--ds-gap-loose)">
<span class="section-head-kicker">A WIDER GAP</span>
<span class="placeholder-caption">One variable, set on the container.</span>
</div>
</div>One thing at each end
cluster-ends pushes the children apart and lets them fall back into an ordinary cluster when the line runs out. Narrow the stage. The gap is still doing work at the moment they wrap, which is why this is a variant rather than a rule of its own.
<div class="cluster cluster-ends" style="width:100%">
<span class="byline">Free for personal use. By installing it you accept the licence.</span>
<span class="cluster">
<a class="chip" href="#">English</a>
<a class="chip" href="#">Polski</a>
<a class="chip" href="#">Deutsch</a>
</span>
</div>Two doors that read as a pair
cluster-stretch hands every item the row's own height. A button is as tall as its padding plus whatever is inside it, so an icon in one of two buttons makes it the taller — 50px against 43px, measured. Nothing is wrong with either one; they simply have different things in them.
<!-- The same pair twice. Above, the default: each door is as tall as whatever
is inside it, and the icon in the first one makes it the taller. Below,
`cluster-stretch`, where the row hands both of them its own height. -->
<div class="flow">
<div class="cluster">
<a class="btn btn-primary" href="#">
<svg class="icon" viewBox="0 0 24 24" aria-hidden="true">
<path d="M12 3v10m0 0 4-4m-4 4-4-4M4 17v3h16v-3" fill="none" stroke="currentcolor" stroke-width="2" />
</svg>
GET IT
</a>
<a class="btn" href="#">READ MORE</a>
</div>
<div class="cluster cluster-stretch">
<a class="btn btn-primary" href="#">
<svg class="icon" viewBox="0 0 24 24" aria-hidden="true">
<path d="M12 3v10m0 0 4-4m-4 4-4-4M4 17v3h16v-3" fill="none" stroke="currentcolor" stroke-width="2" />
</svg>
GET IT
</a>
<a class="btn" href="#">READ MORE</a>
</div>
</div>Reference
Read from primitives/cluster.css when this page was built, so it cannot fall behind the stylesheet.
.cluster.cluster-ends.cluster-stretch--cluster-gap — falls back to --ds-gapNotes
A column-gap alone looks right until the row wraps, and then the second line sits flush against the first. That is the case nobody tests, so it is the case this makes impossible. Narrow the window on the chips above.
Flow is the vertical rhythm of a page column and its step is a typographic decision; this is a row of siblings and its gap is the ordinary one. Two names because they are two decisions. Split lays two COLUMNS that become one and gives each an equal share; this lays items out at their own widths and wraps when it runs out of room. A cluster of two is not a split of two.
chip-row is this exactly, and it was written before this existed. hero-actions was the other one and is a cluster now — because the copy is what made the variant above unreachable from a hero. A primitive's modifier cannot tune a section's own row: the section layer is later and wins whatever the modifier says. That is what a hand-written copy costs, stated as a fact rather than as a worry. A third is not a thing anybody may add.