Grids
tier 2 — classesThree layout primitives, all breakpoint-free: they respond to the space they are given rather than to the viewport width, so they behave correctly inside a narrow column too.
.card-masonry
Cards of similar height flow across as many balanced columns as the width allows, and
stack to fill each column instead of piling into one strip. Every child is kept whole.
auto-fit collapses empty tracks, so the cards that are present always
stretch to fill the row — remove one and nothing is left stranded. Resize this window to
watch it recolumn.
<div class="card-masonry">
<div class="card">
<div class="card-head"><strong>Appearance</strong></div>
<div class="card-body" style="display:flex; flex-direction:column; gap:10px">
<label class="form-check"><input type="checkbox" /> Light theme</label>
<label class="form-check"><input type="checkbox" /> Colour-blind palette</label>
<label class="form-check"><input type="checkbox" checked /> Compact tables</label>
</div>
</div>
<div class="card">
<div class="card-head"><strong>Notifications</strong></div>
<div class="card-body" style="display:flex; flex-direction:column; gap:10px">
<label class="form-check"><input type="checkbox" checked /> Desktop notifications</label>
<label class="form-check"><input type="checkbox" /> Sound</label>
</div>
</div>
<div class="card">
<div class="card-head"><strong>Account</strong></div>
<div class="card-body">
<div class="kv"><span class="k">Signed in as</span><span class="v">alex.fischer</span></div>
<div class="kv"><span class="k">Role</span><span class="v">admin</span></div>
</div>
</div>
</div>
.card-grid
A set of peers in a plain wrapping grid. It differs from
.card-masonry in the one way that decides which to use:
auto-fill keeps the track count stable, so three cards stay three columns
wide instead of stretching to fill the row. Use this when the cards are equals of similar
height; use .card-masonry when their heights differ a lot.
<div class="card-grid">
<div class="card">
<div class="card-body">
<div class="kv"><span class="k">Queue</span><span class="v">Fulfilment</span></div>
<div class="kv"><span class="k">Waiting</span><span class="v">12</span></div>
</div>
</div>
<div class="card">
<div class="card-body">
<div class="kv"><span class="k">Queue</span><span class="v">Network</span></div>
<div class="kv"><span class="k">Waiting</span><span class="v">3</span></div>
</div>
</div>
<div class="card">
<div class="card-body">
<div class="kv"><span class="k">Queue</span><span class="v">On call</span></div>
<div class="kv"><span class="k">Waiting</span><span class="v">0</span></div>
</div>
</div>
</div>
.field-grid
Form fields side by side, collapsing to one column below roughly 200px per field. Use it for values that belong together — a from/to pair, a host and port.
<div class="field-grid">
<div class="form-field">
<label class="form-label" for="g-host">Host</label>
<input class="form-input" id="g-host" type="text" value="192.0.2.20" />
</div>
<div class="form-field">
<label class="form-label" for="g-port">Port</label>
<input class="form-input" id="g-port" type="text" value="3306" />
</div>
<div class="form-field">
<label class="form-label" for="g-db">Database</label>
<input class="form-input" id="g-db" type="text" value="orders" />
</div>
</div>
.page holds content to
--page-max (1800px) and centres it by growing its horizontal padding rather than
capping its width, which keeps the scrollbar at the right edge of the screen.
A dashboard row
The composition a dashboard is actually made of: a .stat-row
of figures above a .card-grid of the things behind them. Both are breakpoint-free,
so the whole block behaves correctly inside a narrow column too.
Nothing here is a page-specific grid. If a layout needs a named area or a fixed column count, it belongs in the app that owns the page rather than in this library.
<div class="dr-col dr-gap-3">
<div class="stat-row">
<div class="stat">
<span class="stat-label">Dispatched this week</span>
<span class="stat-value">1,204</span>
<span class="stat-delta stat-delta--good"><i class="ri-arrow-up-line"></i> 8% on last week</span>
</div>
<div class="stat">
<span class="stat-label">Awaiting stock</span>
<span class="stat-value">37</span>
<span class="stat-target">of 1,204 orders</span>
</div>
<div class="stat">
<span class="stat-label">Median time to dispatch</span>
<span class="stat-value">4.2<span class="stat-unit">h</span></span>
<span class="stat-delta stat-delta--good"><i class="ri-arrow-down-line"></i> 20 min faster</span>
</div>
</div>
<div class="card-grid">
<div class="card">
<div class="card-head">
<strong>EU-West</strong>
<span class="health-badge health-badge--live"><span class="health-dot"></span> Live</span>
</div>
<div class="card-body">
<div class="kv"><span class="k">Waiting</span><span class="v">12</span></div>
<div class="kv"><span class="k">Oldest</span><span class="v">2 h 14 m</span></div>
</div>
</div>
<div class="card">
<div class="card-head">
<strong>EU-Central</strong>
<span class="health-badge health-badge--degraded"><span class="health-dot"></span> Degraded</span>
</div>
<div class="card-body">
<div class="kv"><span class="k">Waiting</span><span class="v">25</span></div>
<div class="kv"><span class="k">Oldest</span><span class="v">9 h 02 m</span></div>
</div>
</div>
<div class="card">
<div class="card-head">
<strong>UK-South</strong>
<span class="health-badge health-badge--idle"><span class="health-dot"></span> Idle</span>
</div>
<div class="card-body">
<div class="kv"><span class="k">Waiting</span><span class="v">0</span></div>
<div class="kv"><span class="k">Oldest</span><span class="v">—</span></div>
</div>
</div>
</div>
</div>