# Dashboard tables How every data table on the dashboard is laid out, and the rules a new table must follow so it never grows a horizontal scrollbar on a desktop screen. Everything here is plain CSS in `src/web/tailwind.css` plus four cell classes; there is no table library and no JavaScript involved. ## The problem this solves A table used to be `min-width: max-content` inside a `.scroll-x` wrapper, and most cells were `white-space: nowrap`. Any table whose natural width exceeded the page column (80rem, ~1355px at the site's 110% scale) became a horizontal scroller, even on a 2560px monitor, and the columns that mattered were hidden behind the scrollbar. Wrapping columns were squeezed to their minimum while the nowrap ones kept everything. ## The three rules 1. **Tables get the whole viewport, everything else keeps the page column.** `.dashboard` is a CSS grid with two named column spans: `content` (at most 80rem minus the page gutters, exactly what the header uses) and `wide` (the viewport minus the same gutters). Every direct child sits in `content`; a direct-child `.scroll-x` sits in `wide`. The table inside a wide wrapper is `width: auto` (shrink-to-fit) with `min-width` equal to the content column and `max-width: 100%`, centred. A table that fits the page column therefore looks exactly as before; a table that needs more grows, centred, up to the viewport edge; the page itself never scrolls sideways. 2. **Columns wrap before the table scrolls.** The `min-width: max-content` rule is gone. A table shrinks by wrapping its text columns down to their floors, and only when the floors alone no longer fit (phones, mostly) does the `.scroll-x` wrapper scroll. Headers always wrap. 3. **A cell declares what it holds, and nothing else decides its width.** There are exactly four cell classes: | class | use it for | behaviour | | ------------ | -------------------------------------------------------------- | ---------------------------------------------------------------------- | | *(none)* | short prose, names, tokens, badges | wraps at spaces | | `num` | numbers, money, counts | right-aligned tabular figures; `td.num` never wraps, `th.num` may | | `cell-tight` | timestamps, dates, ids, a single short token that must not split | `white-space: nowrap`. Nothing longer than ~20 characters | | `cell-wrap` | titles, URLs, notes, messages, badge lists, anything free-form | floor 10rem, ceiling 32rem, `overflow-wrap: anywhere` | Anything long that must not wrap gets an inner block with a Tailwind clamp (`