Hairline stat strip
A row of stat tiles joined by hairlines that are grid gap, not borders — the container paints the border color and the tiles paint the surface, so separators never double up or break when the row wraps — in a reporting form and in a second form where each tile is the filter for the list beneath it.
reach for it when building
- summary strip at the top of a detail page
- dashboard KPI row
- account usage overview
- report header figures
- profile stats band
tagged
Reporting only — the figures are the whole job.
Same strip, working as the filter. Press a tile to narrow the list; press it again to clear.
- Bicycle drivetrain teardownDone
- Kiln firing, part threeDownloading
- Field recording — marsh at dawnQueued
- Lathe restoration, episode 12Done
- Sourdough hydration testsFailed
- Bookbinding: the long stitchQueued
Showing all 6 downloads.
<p class="stage__cap">Reporting only — the figures are the whole job.</p>
<div class="hss-strip">
<div class="hss-tile"><span class="hss-label">Documents</span><span class="hss-figure">1,482</span><span class="hss-sub">this period</span></div>
<div class="hss-tile"><span class="hss-label">Median time</span><span class="hss-figure">3.2s</span><span class="hss-sub">last 24h</span></div>
<div class="hss-tile"><span class="hss-label">Clean runs</span><span class="hss-figure">98.4%</span><span class="hss-sub">no retries</span></div>
<div class="hss-tile"><span class="hss-label">Quality score</span><span class="hss-figure is-missing" aria-label="not available">—</span><span class="hss-sub">not rated yet</span></div>
</div>
<p class="stage__cap">Same strip, working as the filter. Press a tile to narrow the list; press it again to clear.</p>
<div class="hss-strip hss-strip--filter" role="group" aria-label="Filter downloads by status">
<button class="hss-tile" type="button" data-status="All" aria-pressed="true"><span class="hss-label">All</span><span class="hss-figure">6</span><span class="hss-sub">downloads</span></button>
<button class="hss-tile" type="button" data-status="Queued" aria-pressed="false"><span class="hss-label">Queued</span><span class="hss-figure">2</span><span class="hss-sub">downloads</span></button>
<button class="hss-tile" type="button" data-status="Downloading" aria-pressed="false"><span class="hss-label">Downloading</span><span class="hss-figure">1</span><span class="hss-sub">downloads</span></button>
<button class="hss-tile" type="button" data-status="Done" aria-pressed="false"><span class="hss-label">Done</span><span class="hss-figure">2</span><span class="hss-sub">downloads</span></button>
<button class="hss-tile" type="button" data-status="Failed" aria-pressed="false"><span class="hss-label">Failed</span><span class="hss-figure">1</span><span class="hss-sub">downloads</span></button>
</div>
<ul class="hss-list">
<li data-status="Done"><span>Bicycle drivetrain teardown</span><span class="st">Done</span></li>
<li data-status="Downloading"><span>Kiln firing, part three</span><span class="st">Downloading</span></li>
<li data-status="Queued"><span>Field recording — marsh at dawn</span><span class="st">Queued</span></li>
<li data-status="Done"><span>Lathe restoration, episode 12</span><span class="st">Done</span></li>
<li data-status="Failed"><span>Sourdough hydration tests</span><span class="st">Failed</span></li>
<li data-status="Queued"><span>Bookbinding: the long stitch</span><span class="st">Queued</span></li>
</ul>
<p class="hss-status" role="status" aria-live="polite">Showing all 6 downloads.</p>.hss-strip {
display: grid;
gap: 1px;
background: var(--border);
border: 1px solid var(--border);
border-radius: var(--radius);
overflow: hidden;
grid-template-columns: 1fr;
}
@media (min-width: 21rem) { .hss-strip { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 42rem) { .hss-strip { grid-template-columns: repeat(4, 1fr); } }
@media (min-width: 42rem) { .hss-strip--filter { grid-template-columns: repeat(5, minmax(0, 1fr)); } }
.hss-tile { background: var(--surface); padding: 0.9rem 1rem; display: grid; gap: 0.3rem; min-width: 0; }
.hss-label {
font: 600 0.8125rem/1.2 ui-monospace, monospace;
text-transform: uppercase;
letter-spacing: 0.06em;
color: var(--dim);
overflow-wrap: anywhere;
}
.hss-figure { font-size: 1.6rem; font-weight: 700; font-variant-numeric: tabular-nums; }
.hss-figure.is-missing { color: var(--dim); }
button.hss-tile[aria-pressed="true"] {
background: color-mix(in srgb, var(--accent) 14%, var(--surface));
}Build a strip of statistic tiles that reads as one joined instrument panel rather than a row of floating cards.
The separators between tiles must not be borders. Make the container a CSS grid with gap: 1px and give the container itself the border color as its background; each tile then paints the surface color on top. The 1px of container showing through the gap is the hairline. This is the entire pattern: real borders double where two tiles meet and leave a stray edge when auto-fit wraps the row, and a gap physically cannot do either.
Pin the column counts rather than letting auto-fit choose them: one column, two from 21rem, four from 42rem. A strip that wraps three-and-one reads as broken.
Tile anatomy: a mono uppercase label, the figure large and bold with tabular numerals, and a one-line qualifier under it.
Two rules of honesty. Render a missing value as a dimmed em dash, never as zero. Keep the unit with the number, so 3.2s and 98.4% are figures and not figures-plus-footnotes.
In the filter form each tile is a toggle button with aria-pressed, not a tab — the list underneath is filtered, not replaced. Compute every count from the unfiltered set so the numbers do not change as you press them.
Build a strip of statistic tiles that reads as one joined instrument panel rather than a row of floating cards. The separators between tiles must not be borders. Make the container a CSS grid with gap: 1px and give the container itself the border color as its background; each tile then paints the surface color on top. The 1px of container showing through the gap is the hairline. This is the entire pattern: real borders double where two tiles meet and leave a stray edge when auto-fit wraps the row, and a gap physically cannot do either. Pin the column counts rather than letting auto-fit choose them: one column, two from 21rem, four from 42rem. A strip that wraps three-and-one reads as broken. Tile anatomy: a mono uppercase label, the figure large and bold with tabular numerals, and a one-line qualifier under it. Two rules of honesty. Render a missing value as a dimmed em dash, never as zero. Keep the unit with the number, so 3.2s and 98.4% are figures and not figures-plus-footnotes. In the filter form each tile is a toggle button with aria-pressed, not a tab — the list underneath is filtered, not replaced. Compute every count from the unfiltered set so the numbers do not change as you press them.
Neighbours in the album
same drawer, different specimens
Cork notice board
Pinned paper notes on a cork board where every texture is layered CSS gradients.
Object-shaped cards
Where a record stands for a physical thing, the card is drawn as that thing — nine variations in pure gradients.
Column-flow wall
Cards flowing down columns instead of across rows, with the reading-order cost stated plainly.