---
title: Dense Operational Table
slug: dense-operational-table
kind: pattern
summary: A tight, scannable grid built for comparing many similar records at once — the default for operational work, and almost always better than cards.
problem: Someone has to work through forty rows and find the ones that need them. Rendered as roomy cards, forty records become a scroll marathon where nothing lines up and nothing can be compared. The information is all there and the screen is still useless.
family: [scan]
data_shape: [collection, tabular]
principles: [minimize-distance, surface-dont-bury, progressive-disclosure]
interaction: [scanning, sorting, selection]
density: high
complexity: low
status: stable
visibility: public
use_when:
  - Records are homogeneous — the same fields mean the same thing on every row.
  - Comparison across records is the job: which is oldest, largest, most overdue.
  - There are more than about fifteen records, or there will be next year.
  - People return to this screen daily and will learn its shape.
avoid_when:
  - Records are heterogeneous, so half the columns are blank for half the rows.
  - There are three records. A table of three is ceremony around a list.
  - The record's value is visual — a photo, a chart, a floor plan.
  - Each record needs a paragraph to make sense. That is a feed, not a table.
alternatives:
  - slug: master-detail-drawer
    when: People need the whole record, not just the comparable fields. Add a drawer to the table rather than widening the table.
  - slug: drawer-vs-modal-vs-page
    when: You have the table and now need somewhere to put the detail.
ask_leo: |
  Render this collection as a dense operational table, not as cards.

  - Pick at most six or seven columns: the identifier, the status, the one or two
    numbers people compare, the owner, and the date that drives urgency. Leave
    everything else off this screen.
  - Right-align numbers and dates and use tabular figures so digits line up
    vertically. Left-align text.
  - Keep the header row visible when the body scrolls.
  - Make the columns people sort by actually sortable, and show which column is
    sorted and in which direction.
  - Use row separators rather than zebra striping, and keep row height tight —
    roughly 36 to 44 pixels.
  - Show status as a word. If you add colour, the word must still carry the
    meaning on its own.
  - Do not add horizontal scrolling to fit more columns. If a column does not
    earn its place, it belongs in the record's detail view instead.
  - Reveal row actions on hover or focus, and keep one primary action per row.
  - On a narrow screen, collapse each row into a stacked summary rather than
    letting the table scroll sideways.
related:
  - title: High-Quality Inline-Editable Table
    url: /cookbook/inline-editable-table
    summary: The implementation, once the table needs to be editable in place.
  - title: Multi-Select, Bulk Edit & Mass Reassignment
    url: /cookbook/bulk-edit-and-mass-reassignment
    summary: What to add when the job is acting on many rows at once, not reading one.
  - title: Progressive Disclosure for Dense Detail Pages
    url: /cookbook/progressive-disclosure-detail-page
    summary: Where the columns you left off this screen should go.
---

## Anatomy

```
┌────────────────────────────────────────────────────────────────┐
│ Customer          Owner      MRR      Renews      Status       │  ← sticky
├────────────────────────────────────────────────────────────────┤
│ Acme Corporation  Dana     $1,200   12 Sep 2026   Active       │
│ Globex            Sam           —   trial, d9     Trial        │
│ Initech           Dana       $400   03 Nov 2026   Active       │
│ Umbrella          —              —  —             Churned      │
└────────────────────────────────────────────────────────────────┘
   left-aligned      ↑ right-aligned, tabular figures   ↑ word first
```

The rules that make it work are unglamorous and all of them are about **alignment**:

- **Numbers right, text left, tabular figures throughout.** A column of right-aligned numbers can be compared by length alone — you spot the outlier without reading a single digit. Proportional figures break this, because a `1` is narrower than an `8`.
- **A sticky header.** Once you have scrolled past it, an unlabelled column is a guessing game.
- **Separators, not stripes.** Zebra striping was a fix for wide tables on low-resolution screens. On a modern screen it adds visual noise proportional to row count.
- **Tight rows.** 36–44px. Every extra pixel of row height is a row that fell off the screen.

## Why it works

**A table is an alignment machine.** The reason it beats cards for this job has nothing to do with taste: values in a column share a baseline and a left or right edge, so the eye compares them preattentively — before reading. Cards destroy that. The same forty records in cards force forty separate readings, because no two values ever line up.

This is the direct application of two principles. **Minimize distance:** related values sit adjacent, so connecting "this customer" to "this renewal date" costs a glance rather than a scroll. **Progressive disclosure:** the table is the overview layer, and everything you left off it lives one click deeper — you are deferring detail, not deleting it.

The density judgment itself is settled house guidance: for long lists, a condensed table beats large white-space-heavy cards; roomy cards are for a few high-importance items.

## Choosing columns

The hard part is not building the table. It is deciding what goes in it, and the failure mode is putting in everything the model has.

Ask one question per candidate column: **would someone ever scan this column to decide which row to open?** If not, it is detail, and detail belongs in the record.

A working budget is six or seven columns:

| Slot | What goes there |
|---|---|
| Identity | The name a person would say out loud |
| Status | Where this record is in its lifecycle |
| Measure | The one or two numbers people compare |
| Owner | Who is responsible, when that matters |
| Time | The date that creates urgency |

If a stakeholder wants an eighth column, something has to come out. The budget is the mechanism; without a fixed cap, every stakeholder's favourite field lands in the table and you are back to a spreadsheet.

## Getting it wrong

- **The horizontal scroll table.** Thirty fields dumped into columns because nobody decided what mattered. Half the data is off-screen, and the half that matters is not reliably the visible half. This is the named anti-pattern *Data dump*, and the cure is the column budget above.
- **Card soup.** Twenty homogeneous records rendered as enormous cards. Usually chosen because cards photograph better, at the cost of the job the screen exists for.
- **Rainbow status.** Six hues at the same saturation, two of them meaning two things each. Colour stops separating anything and the table turns to confetti under a squint test.
- **Centred numbers.** Kills the ragged edge that makes a numeric column comparable at a glance.

## Exemplars

**Stripe's payments list.** Amount right-aligned in tabular figures, status as a word with a small colour dot, everything else deferred. Notable for what is *absent*: the payment object has dozens of fields and about six reach the table.

**Linear's issue list.** Proves density is not the enemy of calm — tight rows, generous horizontal whitespace, and almost no colour, so the few coloured things genuinely mean something.

**Ramp's transactions.** Shows the escape valve done properly: the table stays narrow and disciplined, and the rest of the record opens beside it rather than being crammed into another column.

The extractable rule: **a great operational table is defined by the columns its designers refused to add.**
