Use a native HTML table unless the table itself must behave like a composite widget. Spanning headers, grouped columns, nested details, and a few buttons per row still fit normal table semantics well. Switch to an ARIA grid only when you need managed cell-by-cell focus, arrow-key navigation, or spreadsheet-style editing across the whole surface, because that choice changes both keyboard behavior and screen reader expectations (W3C WAI Tables Tutorial, WAI-ARIA APG grid pattern).
Should this stay a table or become a grid?
Classify the widget by the user’s primary task. If users are reading relationships between rows and columns, keep real table elements: caption, thead, tbody, th, and td. The W3C tutorial is clear that accessibility depends on marking up header and data cells and defining their relationship, not just drawing a visual grid (W3C WAI Tables Tutorial).
Move to role="grid" only if you are intentionally building one focus-managed surface. The ARIA grid pattern says a grid is a composite widget, only one contained item is in the page tab sequence, and the author must manage focus movement inside it (WAI-ARIA APG grid pattern). That is appropriate for bulk editing, cell selection, or dense keyboard-driven data review. It is unnecessary for a reporting table with links and actions.
How should header relationships work when cells span?
Set the logical header model first, then render the visual spanning to match it. That ordering boundary matters: if product code later hides, reorders, or virtualizes columns, you must update the associations too rather than treating accessibility as a final pass.
For simple row and column headers, use scope="row" and scope="col". For irregular structures with grouped headers spanning rows or columns, the W3C guidance points to colgroup and rowgroup scope values. For multi-level headers that cannot be described strictly by row or column direction, use explicit id and headers mappings (W3C WAI Tables Tutorial). The HTML table model still expects one coherent grid even when a cell spans multiple rows or columns (HTML Standard: Tabular data).
What can go inside a complex cell?
A complex cell can contain status, metadata, and actions, but keep one clear reading order: primary value first, supporting detail second, controls last. If every fragment becomes a tab stop, the row turns into a navigation maze.
Prefer a dedicated actions column with one labeled button or menu button over scattering several tiny controls across data cells. For expandable details, keep the disclosure trigger in the row and render the details in the following row with a spanning cell. MDN’s table reference also notes that a cell may span multiple rows and columns and that caption helps users decide whether to inspect the table further (MDN table element reference).
What should we test before shipping?
Use this checklist:
- Screen reader announces the expected row and column headers on spanned cells.
- Tab order follows the work sequence, not just the visual layout.
- Expanded details appear after the owning row and focus returns predictably.
- Hidden or reordered columns do not leave stale
headersreferences. - Mobile card views preserve an equivalent relationship model instead of destroying the table semantics.
Worked example: an operations table with Service as the row header, a grouped Latency header over P50 and P95, a Status cell containing label plus timestamp, and one Actions menu. That should stay a native table. If you later add arrow-key cell movement, inline editing in every latency cell, and row selection shortcuts, redesign it as a real grid instead of partially imitating one.
Q: Can I place form fields inside a table cell? Yes, if the structure is still primarily tabular. Label the field clearly and avoid turning every cell into its own mini form.
Q: Should I add arrow-key navigation to a normal table anyway? No. Either keep native table behavior with ordinary tab order or implement the full grid focus model.
Reviewed: 2026-09-05
Sources are linked throughout this guide. Product capabilities can change; consult the linked documentation for your deployment.
Read our editorial approach ↗