The structure for scanning, comparing, sorting, filtering, selecting, and acting on records that share the same attributes. A data table gives users a stable grid, clear controls, and honest states for loading, empty, filtered, and paginated data.
When to use it
Use the data table when the record set itself is the work: scanning, comparing, sorting, filtering, selecting, and acting on rows.
Use a data table when
Rows share the same attributesUse a table when each record can be compared across stable columns such as status, owner, date, amount, or location.
Users need to scan or compareThe main job is finding differences, spotting outliers, checking status, or choosing which records need attention.
Controls change the result setSorting, filtering, search, pagination, saved views, or bulk selection are part of the task.
Use something else when
The content is not comparableUse cards, lists, or detail pages when each item has different attributes or depends on imagery, long text, or narrative context.
The user is editing one objectUse a form layout or detail page when the task is to create, review, or edit one record at a time.
There are too few attributes to justify a gridUse a simple list when users only need a name, one supporting line, and one action.
Anatomy
The table owns the relationship between controls, result state, headers, rows, and actions. Individual primitives still own their control behavior.
Table title or caption
Required
Name the record set in plain language. The title or caption tells assistive technology users what the table contains.
Use a visible heading near the table and a caption or aria-labelledby connection for the table element.
Toolbar
Conditional
Search, filters, saved views, export, and create actions live above the table when they change or act on the result set.
Keep active filters visible. Do not hide the reason a table changed.
Column headers
Required
Headers are short nouns or noun phrases. Sortable headers expose both the action and current sort state.
Use th scope="col" and aria-sort on the sorted column.
Rows and cells
Required
Cells stay aligned to their headers. Status cells include readable text, not color alone.
Use semantic table markup for comparable data; avoid div grids for ordinary tables.
Selection and row actions
Conditional
Selectable tables show a labeled checkbox per row, a selected count, and actions that apply to the selection.
Do not make the entire row the only interactive target when individual links, checkboxes, or actions are present.
Pagination and result count
Conditional
Large result sets show how many records exist, what page is visible, and how users move through pages.
Keep pagination controls keyboard reachable and preserve filters while changing pages.
Variants
Choose the table variant by the job: compare rows, select work, or recover from an empty filtered result.
Record comparison table
A table optimized for scanning records across stable columns.
Trigger: Users need to compare many records by status, owner, date, amount, or other repeated attributes.
Job: Keep columns predictable, make important status visible in text, and preserve row-to-column alignment.
Selectable work queue
A table for reviewing multiple records and applying a shared action.
Trigger: Users need to select one or more rows before assigning, approving, exporting, or archiving records.
Job: Make selected state, selected count, and available bulk actions explicit without hiding row-level actions.
Filtered empty table
A table state that preserves controls when filters return no rows.
Trigger: Search, filters, or saved views produce no matching records.
Job: Explain the empty result, keep active filters visible, and give a direct recovery action.
Examples
The previews show table controls, row states, active filters, and empty-state recovery in realistic product context.
Vendor compliance
Vendor compliance
Sort by renewal date and scan status before opening a vendor.
Vendor compliance
42 vendors
StatusAllOwnerAll
Sort by renewal date and scan status before opening a vendor.