
Data Tables: Designing for Scanning, Comparing, and Acting
A data table must let people find, compare, and act on rows. How to align numbers, mark sort order, freeze headers, and use W3C's accessible table markup.
What should a table allow people to do?
NN/g describes four tasks a table should support: finding records that fit specific criteria, comparing data, viewing, editing, or adding a single row’s data, and taking action on records (NN/g: Data Tables: Four Major User Tasks, Page Laubheimer, 2022). That list is useful for reviewing any table: if it fails one task, a function is probably missing or a column is in the way.
For finding, NN/g asks for filters that are quick to discover and clearly show when they are active, plus search. For comparing, hiding and reordering columns must be easy, with visible indicators for hidden columns. For acting on several records, the table uses a checkbox per row and action controls above or below the table; a single “Select all” option helps when the same action is commonly applied to the whole dataset. NN/g warns that actions hidden under a hover gesture or a generic “Actions” menu are hard to discover.
When the table is larger than the screen, NN/g recommends freezing header rows and header columns. Borders, zebra striping, and hover highlighting also help people keep their place.
How should numbers and text be aligned?
GitLab’s Pajamas design system gives a concrete rule: text aligns left, not justified or centered, and numeric data can be right-aligned with a consistent number of decimal places to improve scannability (GitLab Pajamas: Table). Aligned this way, units, tens, and hundreds sit in the same vertical position, so values can be compared at a glance.
Pajamas also supports right-aligning the header of a numeric column, even when it is sortable, and notes that alignment within a table matters more than consistency from table to table. The practical rule: the header follows the alignment of its data, and that alignment does not change within a column.
How do you show sort order?
A sortable column should show which column is active and in which direction. In Pajamas, sorting is indicated in the header with an arrow; the first click sorts ascending, and later clicks alternate with descending. IBM’s Carbon system defines three states (unsorted, ascending, descending); only the sorted column shows a permanent icon, and the icons on the other columns appear on hover (IBM Carbon: Data table).
For screen readers, the aria-sort attribute communicates the same state. The sortable table example in the WAI-ARIA Authoring Practices Guide sets it on the th of the sorted column and removes it from the previous column when the sort changes (W3C WAI-ARIA APG: Sortable table). The initial sort depends on use: for a contract list, sorting by due date may be the most useful, but there is no universal rule.
What accessible markup does a table need?
W3C separates three pieces. Header cells are marked with th and data cells with td. With two headers (row and column), the scope attribute with the value col or row declares the direction of each (W3C WAI: Tables with two headers). And the table title goes in a caption element inside table.
For tables with irregular headers, scope also accepts the values colgroup and rowgroup (W3C WAI: Tables with irregular headers). For multi-level headers, each header gets an id and the data cells cite it in their headers attribute, separating several ids with spaces (W3C WAI: Tables with multi-level headers).
A summary of a complex table can go inside the caption, in an element referenced with aria-describedby, or in a figcaption inside a figure. W3C warns that the last option may cause the caption and summary to be read out several times (W3C WAI: Caption and summary).
How does it work on mobile?
Pajamas offers two paths: keep the table layout and allow horizontal scrolling without breaking the page layout, or turn each row into its own group. Its criterion is clear: if rows need to be compared, keep the table; if the content of each row can stand on its own without comparison, stack it. In the stacked version, the sort icon and sort function should not be shown.
So the decision depends on how many columns the person needs to compare. What does not help is hiding columns without warning: if a column is out of view, the person should know it exists and how to see it.
Illustrative example
Illustrative example: a procurement team at a logistics company compares four suppliers on price, delivery time, compliance, and contract terms. The original table had twelve columns, none with consistent alignment, and the header disappeared when scrolling down. The redesign keeps six columns, right-aligns the numbers with two decimals, freezes the header, and marks the active sort column with its direction. On mobile, each supplier appears as a stacked group with the three main metrics, and the other columns sit on a detail screen. The goal is for buyers to choose in fewer steps and stop copying figures into a separate spreadsheet.
If the table works as a listing with many criteria, review filters and faceted search. And if the table takes time to load, loading states explain how to show progress without leaving the screen blank.
Row actions should follow the button hierarchy: one primary action per screen, with the destructive action away from the default focus.
Common mistakes
- Aligning numbers to the center or left, which prevents comparison.
- Having headers aligned differently from their data.
- Marking columns as sortable without showing the active direction.
- Using
divelements to imitate a table without marking up headers, so screen readers cannot connect cells to their headers. - Hiding columns on mobile without letting the person know they exist.
- Placing a destructive action next to a view button with no confirmation.
What you can do tomorrow
- Review your most-used table and check that numbers are on the right with the same decimals.
- Open the code and confirm that headers use
thand that the table has acaption. - Ask two people to find the most expensive record in one column. If they hesitate or reach for a spreadsheet, visible sorting or a filter is missing.