Keep the table header visible while the rows scroll vertically
Aliases: frozen header · sticky thead · column labels on scroll
What it is
Column meaning lives in the header row. If that row scrolls away with the body, cells become numbers without units. A sticky table header keeps the column names at the top of the viewport and lets only records move. It preserves “what this column is,” not a group title and not the identity of a row — those jobs belong to other structures.
Why it happens
Reading a cell is a short loop: look up to the column name, look down to the value. While the header is in view, the top half of the loop is a short saccade; once it has gone, column names live in memory. Many columns, and columns that look alike, scramble that order, especially when several numeric columns sit in a row. Pinning the header brings names back into the field so comparison can continue down a column. The header must overlay the body rather than consume a new strip of scroll: if it only “looks still” while actually pushing content down, one fewer row is visible and the comparison window is stolen. The pinned row also has to read as labels, not as another record.
Studying it
Run comparison tasks on a multi-column numeric table, with the header scrolling away versus pinned. Record column mix-ups (treating column B as A), trips back to the top to re-read the header, and time. Independent variables: column count, visual similarity of columns, viewport height. Dependent variables: identity errors, lookbacks to the original header position. Eye tracking should show periodic long upward saccades when the header is not pinned. Do not test on a two-column table that already repeats the label in every cell — that material cannot show the cost of a missing header.
Where it stops holding
If the whole table fits on one screen, the header never leaves and pinning does nothing. After a narrow-screen reflow that repeats labels next to each value, a second sticky header is redundant. A table that also pans horizontally can keep its header and still lose row identity when the first column slides away — that is a different constraint. Tall headers (stacked groups, filter rows) can eat most of the viewport; a shrunken comparison window is then worse than a forgotten column name, so flatten the header or park filters elsewhere. Print has no scroll, so there is nothing to pin.
Applying it
- Pin the header inside the table’s own scroll container, not to the page; a page-level pin will carry the header onto unrelated sections.
- The pinned header must cover cells sliding underneath it, and must differ from data rows in fill or weight.
- For stacked headers, pin only the level that still names the columns, so three header rows do not occupy the viewport forever.
- How to check: scroll to the middle and the end, then ask “what is this column?” covering memory. A wrong answer, or a scroll back to the top, means the header is not doing its job.