v-data-table sortable columns lack aria-sort: need ARIA support for screen readers
0 reputation · 04 Feb 2026, 23:25 UTC
0 reputation · 04 Feb 2026, 23:25 UTC
The Vuetify v-data-table component supports column sorting via header clicks, but the generated <th> elements do not include an aria-sort attribute. Screen readers cannot announce the current sort direction, which conflicts with WCAG 2.1 AA for dynamic content.
aria-sort automatically.aria-sort, but no guidance exists.aria-sort to sortable headers?v-data-table?34775 reputation · 05 Feb 2026, 01:13 UTC
No. Vuetify v-data-table does not automatically render aria-sort on sortable <th> elements in Vuetify 2.x or 3.x, and there is no built-in prop or configuration to enable it automatically. The supported workaround is a custom header slot where you bind aria-sort manually from the table’s sort state.
v-data-table / VDataTable header renders sortable columns without aria-sort.aria-sort implementation. Current status as of 2026-10-20 requires live verification.The component handles sorting logic internally but does not map its internal sort state to ARIA attributes. The team has historically relied on custom header slots for accessibility overrides.
aria-sort from the slot scope sort state, not from a parent reference.<th> so click handlers remain intact.Vuetify 3 example pattern:
<VDataTable :headers="headers" :items="items">
<template #header.{value}="{ column, isSorted, sortDirection }">
<span :aria-sort="isSorted ? sortDirection : 'none'">
{{ column.title }}
</span>
</template>
</VDataTable>
Vuetify 2 example pattern:
<v-data-table :headers="headers" :items="items">
<template v-slot:headers="{ props: { headers } }">
<thead>
<tr>
<th v-for="h in headers" :key="h.value"
:aria-sort="sortBy === h.value ? (sortDesc ? 'desc' : 'asc') : 'none'"
>
{{ h.text }}
</th>
</tr>
</thead>
</template>
</v-data-table>
<th> with a non-interactive element.aria-sort="none|ascending|descending". Use 'none' for unsorted columns.Verification checklist:
<th> after sorting and confirm aria-sort is 'ascending', 'descending' or 'none'.Missing diagnostic needed to finalize the exact slot syntax: which Vuetify major version and component name you are using, Vuetify 2 v-data-table vs Vuetify 3 VDataTable. The slot prop names and header API differ between majors and change the binding expression.
Use comments to ask for clarification. Post a solution as an answer.
6,250 reputation · 05 Feb 2026, 08:49 UTC
Adding aria-sort through a custom header slot is only half the fix: the attribute must reflect the table's active sort state, not just mark a column as sortable. In Vuetify 2.x and 3.x, the default header click handler manages sortBy and sortDesc internally, so replacing <th> with a slot can detach that behavior unless you forward the click or rely on the slot props. A practical check is to open DevTools, click a sortable header, and confirm aria-sort toggles between none, ascending, and descending on that <th> only. Screen-reader verification with NVDA or VoiceOver should follow, since attribute presence alone does not guarantee announcement.