Skip to content
TablePage.ai Open the app

Make Data-Table Sorting Work by Keyboard—and Expose Its State

Implement and test sortable table headers with native buttons, persistent focus, aria-sort state, visible direction cues and keyboard checks.

Share X in f
Wei Hu

A sortable public data table needs to do more than rearrange rows after a click. A keyboard user must be able to reach each sortable header, activate it, see where focus remains and determine the resulting sort direction.

Use this target behavior for a sample grants table:

  • Input: columns for Recipient, Award date and Amount.
  • Action: Tab to Amount, then press Enter or Space.
  • Result: rows reorder by amount, focus stays on the Amount control, and the header exposes whether the order is ascending or descending.

The spreadsheet determines the values available to sort. The rendered web page determines whether sorting is accessible. Preparing a clean CSV or XLSX file cannot compensate for an inaccessible header control.

Put a real button inside each sortable header

Keep the native table structure. In a sample grants table, the markup hierarchy should be:

  • a table element;
  • a caption that identifies the dataset and briefly says that header buttons sort columns;
  • a thead containing one th with scope="col" for each column;
  • a native button inside each sortable th;
  • a tbody containing the published data rows.

For the currently sorted Amount column, set aria-sort="descending" on its th. The Amount button can include a down arrow inside a span with aria-hidden="true", preventing that decorative character from becoming part of the button’s accessible name.

The W3C’s sortable-table example uses native HTML table elements, wraps sortable header labels in buttons and places aria-sort on the currently sorted header.

A native button is preferable to a clickable th, div or icon. It enters the normal tab order and receives standard browser button behavior. The W3C example lists separate keyboard support as unnecessary because browsers provide the buttons’ keyboard functionality. WCAG’s keyboard guidance recommends following platform conventions as a best practice rather than making readers learn an unusual key command.

Use proper header associations independently of sorting. For a simple table, that generally means th with scope="col"; more complex header structures need additional planning. See accessible column and row headers for those relationships.

Update the state as one operation

When a reader changes the sort:

  1. Reorder the body rows.
  2. Remove aria-sort from the previously sorted header.
  3. Add aria-sort="ascending" or aria-sort="descending" to the new header.
  4. Update its visible direction indicator.
  5. Keep keyboard focus on the button that was activated.

Only the header representing the active sort should carry aria-sort. The W3C pattern removes the attribute from the old header when the sorted column changes. Its values identify ascending and descending order; the ARIA specification defines the attribute as indicating whether table or grid items are sorted in ascending or descending order.

Do not put aria-sort on the button or table. It belongs on the applicable header cell. Do not use aria-pressed as a substitute: a sort direction is not simply an on/off pressed state.

Avoid rebuilding the table header after every sort. Replacing the focused button can send focus elsewhere or make it disappear. Reorder existing body rows and update the existing header instead. A visible focus indicator must remain available while a keyboard-operable interface is in use, according to the WCAG Focus Visible explanation.

Make direction visible without polluting the name

Show the active direction with an arrow, text such as “ascending,” or both. If an arrow is decorative because aria-sort already supplies the programmatic state, hide it from assistive technology with aria-hidden="true". Otherwise a screen reader may include an unhelpful character name in the button label.

Do not distinguish states by color alone. The W3C example also recommends that any icon marking an unsorted-but-sortable column differ in shape—not merely color or size—from ascending and descending icons.

A short instruction in the caption can explain that header buttons sort the table without repeating the same instruction in every button name. The caption should still identify the dataset; a separate concise summary can explain its scope, units and missing values. The guide to data-table captions and summaries covers that content.

Test the published page, not just the component code

Run this check against the final public URL at desktop and narrow viewport widths:

Check Action Expected result
Reachability Tab from the page controls into the table Every sortable header button receives focus in a logical order; static headers do not create extra stops.
Activation Press Enter, then Space, on a sortable header Each key triggers one sort and does not scroll the page unexpectedly.
Focus Sort repeatedly and switch columns Focus remains visibly on the activated header button.
State Inspect the accessibility tree and use a screen reader The active header exposes ascending or descending state; old headers no longer expose a sort state.
Visual cue Check normal, zoomed and high-contrast views The active column and direction remain distinguishable without color alone.
Data result Test text, numbers, dates, blanks and equal values Rows stay intact and values sort according to the documented data type and missing-value policy.

For the screen-reader check, test combinations your audience actually uses. W3C labels its example as illustrative rather than production-ready and says browser and assistive-technology support can vary. Do not infer conformance from markup inspection alone.

If the sort state is not announced reliably in the combinations you support, first verify that focus stays on the same native button and that aria-sort changes on its parent th. Consider an additional concise status message only after testing, because it can duplicate the header-state announcement in combinations that already expose it.

When publishing through TablePage or another hosted data-page service, apply the same checks to the generated page after relevant interface releases. This assesses the behavior readers receive without claiming that an untested publishing interface passes accessibility requirements.