Responsive data tables

Share table state before building a separate mobile view

Put filters, ordering and selection above the presentation layer. Desktop rows and mobile summaries should act on the same identified records.

In this article

Define stable query and record contracts

Represent filters and sorting explicitly, using a URL state model where sharing and browser navigation are useful. Validate those values before sending them to the server.

Use a durable record ID for selection and actions. Never use the visible row index as the business identity. Pagination and sorting can change that index without changing the underlying record.

The following illustrative state selects two jobs independently of their current visual position.

JSON example
{
  "filters": { "status": "overdue" },
  "sort": { "field": "dueAt", "direction": "asc" },
  "pageSize": 25,
  "selectedIds": ["job-example-17", "job-example-42"],
  "selectionScope": "explicitRecords"
}

Build the comparison view with real semantics

Use table headers that describe the cells beneath them and a label that identifies the dataset. Put sort controls inside the relevant headers and expose the current ordering state.

Give row actions names that distinguish their target where needed. A screen-reader list of twenty buttons all called Open is less useful than actions associated clearly with their job.

Keep long values within the table's intended overflow or wrapping rules. Avoid arbitrary character truncation that removes the only distinguishing part of a record name.

Adapt the presentation, not the business rules

A mobile summary can prioritise job name, status and due time, with secondary fields in a detail view. Reuse the same query and action handlers so permissions and selection do not drift between layouts.

Do not render two complete interactive copies and merely place one off-screen. Ensure the inactive presentation is not exposed to keyboard navigation or assistive technology.

For tasks requiring column comparison, retain a bounded scrollable table and test its operation. Cards are an option, not an automatic requirement at a breakpoint.

Preserve context across updates

Keep the user's selection and navigation context under an explicit policy when data refreshes. If a selected record disappears or becomes ineligible, explain that before a bulk action.

After returning from detail, restore the useful query state and position where practical. Verify direct links, refresh and Back navigation as part of implementation, since those paths often reveal state stored in the wrong component.

Primary sources

W3C APG: table patternW3C WAI: tables tutorial

References checked 11 September 2026.