Portfolio/Writing/The table that had to fit on one screen

The table that had to fit on one screen

A requirement like "twenty-three columns, no horizontal scroll" describes a solution, not a problem. What squeezing a wide table into one viewport does to hierarchy, legibility and scanning, how operators actually work a data grid, why losing row identity is the real cost of scrolling sideways, and the interface details and measurements that settle the argument.

"Show all twenty-three columns, and no horizontal scroll." It is one of the most common briefs in back-office work, and it is a good example of a requirement that describes a solution instead of a problem. Read carefully, it contains two demands that cannot both be met at a readable size, and only one of them is a user need. The other is a reaction to how a scrollbar looks in a demo.

About the scenario
The case below is a composite of several projects, and every number is illustrative. The pattern is common. The specifics are not from any one team.

The brief, and what it actually specifies#

The starting point is usually a spreadsheet the operations team has used for years. Twenty-three columns, each added at some point because somebody needed it once. The product owner treats it as the requirements document, and the reasoning is understandable: it is the only artifact that shows what people work with.

But a spreadsheet that has accreted for years is a record of accumulated requests, not a model of the work. It says nothing about which columns are used to make a decision, which are used to check something occasionally, and which were needed once for an audit. If the table is built from that list unedited, it inherits the flat hierarchy: every column is equally important because nobody has ever said otherwise.

"No horizontal scroll" is rarely a statement about the user's task. It is usually a statement about how the demo feels.

What fitting it in does to the interface#

Twenty-three columns in a 1440 pixel viewport leaves roughly sixty pixels each. To make that work, type drops to nine or ten pixels, padding disappears, headers get abbreviated and every cell truncates. It technically satisfies the brief. It also removes most of what makes a table usable.

Fit it all on one screen
Twelve of the twenty-three columns, shrunk until nothing scrolls
Orders4,31823 COLUMNS
FiltersExport
OrderCustomerEmailCountryCarrierPromisedStatusItemsTotalPaymentChannelWarehouse
10482913Northline Sportswear Ltdn.sportswear@northline.exampleUnited KingdomDPD Express2026-09-21Awaiting pick141,284.00CardWholesaleWH-NORTH-02
10482914Urban Running Co.orders@urbanrunning.exampleNetherlandsPostNL Parcel2026-09-20Late3212.50InvoiceWebWH-EAST-01
10482915Camille Bertrandcamille.b@mail.exampleFranceColissimo2026-09-22Ready189.00CardMarketplaceWH-WEST-04
10482916Trailhead Outfittersbuying@trailhead.exampleGermanyDHL Paket2026-09-19Late273,940.20InvoiceWholesaleWH-NORTH-02
!The demo used clean data and short names, so it fit. Production data has 24-character company names.
This is what 'no horizontal scroll' costs. Every column is technically visible. The one the operator needs, the status, is the same size as the one nobody has ever looked at.
  • Hierarchy collapses. With equal width, equal weight and equal type size, the status column that drives every decision looks identical to the warehouse code nobody reads. Scanning has no landmarks.
  • Legibility fails at production content. A demo with "Acme" and "Paris" fits. Real data has "Northline Sportswear Ltd" and "PostNL Parcel", and both become "North…" and "PostN…". Reviewing a dense table with mock data is one of the most reliable ways to approve something that will not work.
  • Tiny text costs accuracy, not just comfort. Nine pixel numerals invite misreads on exactly the columns, totals and dates, where a misread is expensive.
  • Truncation hides the discriminating part. Cutting at the end of a string is fine for names and harmful for identifiers, where the distinguishing characters are often at the tail.

How operators actually work a grid#

The useful step, and the one that is nearly always skipped, is watching someone do the job with real data for an hour or two. Not an interview about the table, an observation of the task. The behaviors that tend to show up are consistent enough to be worth writing down.

  • The table is a queue, not a report. Most sessions start with a filter and a sort, and the work is narrowing a large set to the few rows that need attention. Reading the grid edge to edge is rare.
  • Scanning locks onto identity plus one or two decision columns. The rest of the row is visual noise sitting between the columns that matter.
  • Detail comes from opening the record. When a value needs a closer look, the natural move is to drill in, not to search sideways across a wide grid.
  • Extra columns are tied to specific jobs. Chasing late shipments needs the carrier. Handling returns needs the payment method. These are episodes, not the default state.
  • Workarounds are the signal. A second spreadsheet, a pasted list of order numbers, a sticky note. Each one marks a place where the table is not showing the right thing at the right moment.
What the operator actually reads
Eleven of twenty-three columns, ranked by how often anyone looks
ORDERS TABLE · ILLUSTRATIVE SHAPE
Columns glanced at, per row handled
ILLUSTRATIVE
Order IDEVERY ROW
StatusEVERY ROW
CustomerEVERY ROW
Promised dateEVERY ROW
TotalOFTEN
CarrierWHEN LATE
CountrySOMETIMES
Payment methodRARELY
ChannelRARELY
Warehouse codeROW DETAIL
Gift wrap flagROW DETAIL
Illustrative, not measured. The shape is the point: a handful of columns carry the decision and a long tail carries almost nothing. Your own table has its own shape, and you can find it.

A caveat worth stating plainly: three or four operators is a hypothesis, not a finding. It is enough to tell you the question you should be asking and to challenge an assumption, and not enough to delete a column. Which is exactly why the measurement section below exists.

The cost of horizontal scroll is not the scrollbar#

Horizontal scrolling in a data grid is not inherently a failure. Spreadsheets have used it for decades. What hurts is the specific thing that goes wrong when you scroll: you lose the row's identity. Six columns to the right of the order number, you are looking at a carrier and a warehouse code and have to remember which order they belong to. That is a working-memory tax, and it compounds across fifty rows.

Comparison across columns has a related cost. The further apart two values sit, the harder it is to relate them, which is why proximity is one of the strongest grouping cues we have. A layout that pushes related fields to opposite ends of a wide grid is working against the way people read.

So the design question is not "how do we avoid scrolling" but "how do we make scrolling cheap". A pinned identity column and a sticky header remove most of the penalty. Grouping related columns next to each other removes more. Once those are in place, the scrollbar stops being a defect and becomes ordinary behavior for a dense grid.

Priority, not width#

The underlying problem was never that the columns did not fit. It was that nothing ranked them, so the only lever left was width. Ranking is an information hierarchy exercise, and a useful way to do it is by asking one question of each column: must this be read before someone can decide what to do with the row?

The real problem
The screen is not the constraint. Priority is.
🎯ALWAYS ON
Decide
Order, status, customer, promised date, total. What you need to pick the next action.
🔎ONE CLICK
Context
Carrier, country, payment. Pulled in by a saved view or the column chooser.
📄IN THE ROW
Reference
Warehouse code, gift wrap, channel. Lives in the row detail and the export.
The question nobody asked
"Which columns do you need to read before you can decide what to do with this row?"
Nobody had ever sorted the columns by what they are for. Once they are sorted, the layout mostly decides itself.

Three tiers usually fall out. The first is what the decision needs, always visible. The second is context that a specific job needs, reachable in one action through a saved view or a column chooser. The third is reference data that lives in the row detail or the export. This is progressive disclosure applied to a grid, and it is the same move that makes any dense interface manageable: show what supports the primary task, make everything else easy to reach and not always present.

Roles and jobs are different axes

One wrinkle is that "the user" is rarely singular. A fulfilment operator, a customer support agent and a finance analyst may use the same table for three different jobs. Defaults should serve the most frequent role, saved views should serve the recurring jobs, and the export should serve the person who genuinely needs every field for reconciliation. Forcing one column set on all three is how you end up at twenty-three.

The details that make a dense table work#

Reducing the default column count buys room. What you do with the room is what separates a table that can be scanned from one that has to be read. A short list of details does most of the work.

Details that carry a dense table
Same data. One version can be scanned, the other has to be read.
Common defaults
OrderCustomerTotalStatus
10482913Northline Sportsw…1,284.00●
10482914Urban Running Co.89●
10482915Camille Bertrand3,940.2●
10482916Trailhead Outfitt…212.5●
Left-aligned numbers with ragged decimals. Status carried by colour alone.
What holds up
OrderCustomerTotalStatus
10482913Northline Sportswear Ltd1,284.00● Ready
10482914Urban Running Co.89.00▲ Late
10482915Camille Bertrand3,940.20● Ready
10482916Trailhead Outfitters212.50▲ Late
Right-aligned, fixed decimals. Status is icon, text and colour together.
None of these is a visual flourish. Alignment, redundant status encoding and sensible truncation are what let a person compare fifty rows without effort.
  • Alignment follows data type. Text left, numbers right, with a consistent number of decimals and tabular figures, so digits line up and magnitude is visible at a glance.
  • Status is never colour alone. Pair colour with an icon or text. It is an accessibility requirement (colour cannot be the only means of conveying information) and it also survives a poor monitor and a glance from across the desk. See the European accessibility picture for why this now carries legal weight.
  • Truncate deliberately. End truncation for names, middle truncation for identifiers, wrapping for long free text, and a way to reach the full value that is not hover-only.
  • A sticky header and a pinned identity column. These two make horizontal and vertical scrolling cheap.
  • Density as a user setting. Compact, default and comfortable row heights let a power user trade whitespace for rows without a redesign.
  • Persist the user's choices. Column order, visibility, width and sort should survive a reload. A table that forgets its configuration teaches people to stop configuring it.
  • Keyboard and selection are part of the design. Row focus, range selection and bulk actions are the difference between a grid people tolerate and one they work fast in.
Default six, everything else one click away
Readable at a glance, and it still scrolls when the job needs it
Orders4,318
Columns 6 / 23Export all 23
All openLate (312)ReturnsWholesale+ Save view
📌 OrderCustomerStatusPromisedTotalAction
10482913Northline Sportswear LtdAWAITING PICK2026-09-211,284.00Open
10482914Urban Running Co.LATE2026-09-20212.50▾ Details
10482915Camille BertrandREADY2026-09-2289.00Open
10482916Trailhead OutfittersLATE2026-09-193,940.20Open
ORDER 10482914 · ROW DETAIL
Urban Running Co.
LATE, 2 DAYS
CarrierPostNL Parcel
WarehouseWH-EAST-01
PaymentInvoice, net 30
ChannelWeb
The first column stays pinned so identity is never lost. Saved views bring in the extra columns for a specific job, and the row detail holds the long tail.

Answering the stakeholder concern#

The product owner's worry, that a scrollbar or a hidden column reads as unfinished, is a legitimate one and deserves a designed answer instead of a dismissal. The way to address it is to make the reduction look deliberate: a visible "Columns 6 / 23" control so nobody wonders whether data is missing, named saved views for the recurring jobs, a pinned first column, an export that carries everything, and a demo run on production-shaped data so the table looks its best at real content lengths.

Framing helps too. "We are showing the six columns that support the decision, and the other seventeen are one click away" is a stronger position than "we could not fit them". The first describes a product choice. The second describes a limitation.

Measure it, do not argue it#

The reason this argument runs on opinion is that the data is rarely collected. A handful of events answers most of the column question, and it is cheap to add at launch.

Check it, do not guess it
Four signals that answer the column question
TABLE TELEMETRY · PER ROLE
What to log on any big table
4 SIGNALS
Columns addedwhich, from where, by whom
Columns hidden againwhat people remove
Horizontal scrolland was the pinned column visible
Row opensper rows handled, per role
None of this needs a research budget. It needs five events and someone willing to read the result before the next redesign.
text
# five events are enough to start
table.column_added     { table, column, view, role }
table.column_removed   { table, column, view, role }
table.hscroll          { table, pinned_column_visible }
table.row_opened       { table, visible_column_count, role }
table.view_applied     { table, view, role }

Read the result by role, and read it alongside qualitative observation. Low usage of a column is a reason to ask why, not a reason to remove it: it might be a compliance field, a rare but critical check, or a column people cannot find. The point is to turn a stakeholder disagreement into a shared look at what people actually do.

Before signing off a wide table#

  1. Can the team state, per column, whether it is needed to decide, needed for a specific job, or reference only?
  2. Has the table been reviewed with production-shaped data, including long names, empty values and large numbers?
  3. Is there a pinned identity column and a sticky header, so scrolling never costs context?
  4. Do alignment, number formatting and status encoding follow the data, and does status work without colour?
  5. Are hidden columns discoverable, with a visible count, saved views for recurring jobs and a full export?
  6. Are column choices persisted per user, and is the default owned by someone who can also remove a column?
  7. Are the table events logged, and is there a date to revisit the default against real behavior?

This is the same discipline as writing a proper ticket, and the same gap as a screenshot-only spec: the picture is fine, but nobody wrote down what the table is for. It ties directly to the argument in who should write the frontend ticket and to the density discussion in the UX nobody sees.

The honest bill#

  • Hiding columns has a discoverability cost. The column chooser needs a visible count and a first-run hint, or some users will conclude the data is gone.
  • A changed default is a real disruption for people who have built muscle memory on the old layout. Saved views and remembered preferences are load-bearing here, not extras.
  • Someone has to own the default. If every stakeholder can add a column and none can remove one, the table drifts back to twenty-three within a year.
  • Some roles genuinely need many columns at once, for reconciliation or audit. That is a valid case, better served by a dedicated view or export than by making every user carry it.
  • Low usage is not proof a column is dispensable. Some columns exist for legal or operational reasons and are rarely read.
Summary
"Fit it on one screen" is usually a comfort constraint dressed as a design requirement. Meeting it by shrinking type and truncating everything removes hierarchy, legibility and scannability, which is most of what a table is for. The stronger approach is to rank columns by their role in the decision, pin identity so scrolling stays cheap, put the long tail one action away, get the alignment, status and truncation details right, and measure what people actually add. The scrollbar was never the defect. The missing priority was.

Next up
Who should write the Jira ticket a frontend developer builds from?

A screenshot and a one-line title is not a ticket, it is a bet that nobody will ask about the empty state. Who should actually draft frontend tickets (product, tech lead, or the assignee), how much detail is realistic on a team trying to ship fast, what a good one contains, and how it should get validated before anyone starts building.

Read next →