aria-sort
On a column or row header in a sortable grid or table, announces the current sort direction. Values: "ascending", "descending", "other", or "none". Only one header in the table should carry a sorted value at a time.
When to use
On role="columnheader" or role="rowheader" (or a native <th> acting as one) in a grid or table that the user can re-sort. The attribute tells AT both that the column is sortable and which way it is currently sorted, so a screen-reader user hears “Last name, sorted ascending” before reading down the column.
If the column is not sortable, do not put aria-sort on it. The attribute is the contract that says “you can change this”.
How it behaves
Accepts four token values:
"ascending"— A→Z, 0→9, oldest→newest."descending"— Z→A, 9→0, newest→oldest."none"— sortable, but not currently sorted by this column. This is the default state once another column takes over."other"— sortable, currently sorted by a non-alphabetic, non-numeric rule that doesn’t fit ascending/descending (a custom relevance score, for example). Rare in practice.
Only one header per table should carry "ascending", "descending", or "other" at a time. When the user changes the sort, set the new column to its new value and reset the previous column to "none" (or remove the attribute).
aria-sort is purely an announcement. The actual sort behaviour — click handler, keyboard activation, the row reordering — is your job. AT does not sort the table for you.
Common failures
- Updating the visible sort indicator (arrow icon) but forgetting to update
aria-sort. Screen-reader users hear the wrong direction. - Leaving two columns with
aria-sort="ascending"after clicking a new header. The first column is no longer driving the sort but still claims to. - Putting
aria-sorton a non-sortable column. AT promises sort behaviour the user can’t actually trigger. - Using a value outside the four allowed tokens —
aria-sort="asc"is invalid and ignored. - Forgetting that the header must be activatable by keyboard.
aria-sortdoes not make the column header focusable; that’s on you. - Treating
aria-sortas the source of truth instead of derived from your sort state. After a re-render that loses the attribute, the announcement disappears.
Example
<table>
<thead>
<tr>
<th
scope="col"
aria-sort="ascending"
>
<button type="button">Last name</button>
</th>
<th scope="col" aria-sort="none">
<button type="button">First name</button>
</th>
<th scope="col">Email</th>
</tr>
</thead>
<tbody>
<!-- … rows sorted by Last name ascending -->
</tbody>
</table>