Accessibility (WCAG 2.1 AA)
Every TableCrafter table ships WCAG 2.1 AA accessibility by default: 44px touch targets, semantic ARIA labels, live screen reader announcements, full keyboard navigation, and automatic high contrast and reduced motion support. No extra shortcode attributes are required.
Overview
Accessibility is built into the TableCrafter rendering engine rather than bolted on as an option. Whether you render a table through the [tablecrafter] shortcode, the Gutenberg block, or the Elementor widget, the same accessibility layer applies. Tables are rendered server-side with valid HTML table markup, then enhanced on the client with ARIA roles, live regions, and keyboard handlers.
The accessibility subsystem is enabled by default and covers six areas: semantic ARIA structure, screen reader announcements, keyboard navigation, focus management, touch target sizing, and respect for user system preferences (high contrast and reduced motion).
There is no accessibility="true" attribute to set. Accessibility features activate automatically on every table. This page documents the real behavior so you can verify, theme around, and test it.
Semantic Markup and ARIA
The server-rendered table uses standard, crawlable HTML: <table>, <thead>, <tbody>, <th>, and <td>. The client layer then enhances it with ARIA so assistive technology can describe the grid accurately.
| Attribute / Role | Applied to | Purpose |
|---|---|---|
| scope="col" | Header cells (<th>) | Associates each header with its column for screen readers. |
| role="columnheader" | Header cells | Identifies sortable column headers in the grid. |
| aria-sort | Sortable headers | Reports the current sort state: none, ascending, or descending. Rendered server-side and kept in sync on the client. |
| role="gridcell" | Data cells (<td>) | Identifies interactive data cells within the table. |
| aria-label | Table, search, pagination, sortable headers, editable cells | Provides descriptive labels (translatable via the plugin i18n layer). |
| aria-describedby | Table element | Points to a visually hidden summary of row count, column count, and available features. |
| aria-current="page" | Current pagination button | Marks the active page in the pager. |
| aria-busy="true" | Loading container | Signals that data is loading so screen readers announce the busy state. |
| role="searchbox" | Search input | Identifies the live search field. |
| role="navigation" | Pagination wrapper | Exposes the pager as a navigation landmark. |
The server-rendered header markup looks like this, so the correct sort state and focusability are present even before JavaScript runs:
<th class="tc-sortable" tabindex="0" aria-sort="none" data-field="price">Price</th>
Screen Reader Support
TableCrafter injects a visually hidden ARIA live region (the announcer) into the page so that dynamic changes are spoken without moving focus. The announcer uses aria-live and aria-atomic="true", with a default politeness of polite and a short delay before each announcement so it is reliably picked up.
Announcements fire automatically for the operations users care about:
- Data loaded — announces the number of rows available once data arrives.
- Sorting — announces the active column and direction, e.g. "Table sorted by price, ascending order."
- Filtering / search — announces the number of matching results, debounced as the user types.
- Pagination — announces "Page X of Y loaded" on navigation.
- Editing context — announces editing, cancel, and saved states where inline editing is available.
When a sortable header receives focus, the announcer also reads the column name, its current sort state, and the activation hint ("Press Enter or Space to sort"), giving non-visual users the same context a sighted user gets from the arrow indicator.
Keyboard Navigation
The entire table is operable without a mouse. The container is made focusable, and a keyboard handler maps standard keys to grid actions. Sortable headers carry tabindex="0" so they are reachable in the normal tab order.
| Key | Action |
|---|---|
| Tab / Shift+Tab | Move between interactive elements (search, headers, pager, controls). |
| Arrow Up / Down | Move focus vertically between cells in the same column. |
| Arrow Left / Right | Move focus horizontally between cells in the same row. |
| Home / End | Jump to the first or last cell in the current row. |
| Page Up / Page Down | Go to the previous or next page when focus is within the pager. |
| Enter / Space | Activate the focused element — sort a header, trigger a pagination button, or begin editing an editable cell. |
| Escape | Cancel an in-progress edit, close an open modal, or clear the search field. |
| Ctrl+F / Cmd+F | Move focus directly to the table search input. |
Arrow-key and Home/End navigation only intercept keys while focus is inside the table, so they never hijack the rest of the page. Outside the table, default browser behavior is preserved.
Focus Management and Indicators
Focus is tracked as it enters and leaves elements, and a high-visibility indicator is applied so keyboard users always know where they are. The default focus ring is a 3px solid outline (#005fcc) with a 2px offset, exceeding the AA non-text contrast requirement against typical table backgrounds.
Context-specific focus styling helps distinguish element types:
- Sortable headers tint toward a light blue background when focused.
- Editable cells tint toward an amber background when focused.
- The global search field shows a focus ring via box-shadow.
You can re-theme these states by overriding the focus rules. They are applied with !important to survive aggressive theme resets, so use an equally specific selector:
/* Override the default focus ring */
.tc-wrapper *:focus {
outline: 3px solid #1a7f37 !important;
outline-offset: 2px !important;
}
Touch Targets (44px Minimum)
On touch and mobile contexts, all interactive controls meet the WCAG 2.5.5 target-size guidance with a 44px minimum. This applies to sortable headers, pagination buttons, filter inputs and selects, the export control, and bulk-action buttons. The rules are scoped both to mobile breakpoints and to any coarse-pointer device via the @media (pointer: coarse) query, so a touchscreen laptop benefits too.
- Mobile and touch devices: interactive elements use
min-height: 44px(andmin-width: 44pxfor square controls like pager buttons). - Very small screens: targets relax to a still-comfortable 40px to fit narrow viewports.
- Touch feedback: cards and controls use a subtle active-state scale, and hover styles are removed on touch devices to avoid sticky states.
On mobile, tables reflow into a card layout that is also fully accessible: the card container is exposed as role="list" and each card as role="listitem", so screen readers announce the data as a navigable list rather than a broken table.
Filter and search inputs use a 16px font size on mobile specifically to prevent iOS Safari from auto-zooming when the field is focused — a small but important usability detail for touch users.
High Contrast and Reduced Motion
TableCrafter detects user system preferences at runtime and re-applies them if they change mid-session, without a page reload.
- High contrast: when
prefers-contrast: highis set, the table adds a high-contrast class that forces black borders, black text on white backgrounds, and a strong red focus outline with a yellow focus background. - Reduced motion: when
prefers-reduced-motion: reduceis set, animations and transitions are effectively disabled (durations collapse to near-zero) and smooth scrolling is turned off.
The plugin also includes baseline color-contrast tuning for sortable and editable cells and support for text scaling up to 200% via word-wrapping rules, so zoomed layouts do not clip content.
If you need high contrast on all the time for a specific deployment, you can add the class to the wrapper yourself:
/* Force high-contrast styling regardless of OS setting */
.tc-wrapper {
/* add the tc-high-contrast class via a small JS snippet or filter */
}
Verifying Accessibility on Your Site
A standard table needs nothing special to be accessible:
[tablecrafter source="https://api.example.com/products.json" search="true" per_page="10"]
To confirm compliance after embedding a table:
- Keyboard pass: Tab into the table, sort a column with Enter, page with Page Up / Page Down, and clear the search with Escape — all without a mouse.
- Screen reader pass: with VoiceOver, NVDA, or JAWS active, sort and search and confirm the announcer reads the new state and result counts.
- Contrast pass: enable your OS high-contrast / increased-contrast setting and reload to confirm the high-contrast styling engages.
- Touch pass: on a phone or with device emulation, verify controls are at least 44px and the table reflows into accessible cards.
Aggressive theme CSS or third-party "table styler" plugins can strip the focus outline or shrink touch targets. If an audit flags missing focus rings or small targets, check for a theme rule overriding .tc-wrapper *:focus or the min-height: 44px declarations before assuming a plugin issue.
Next, see mobile-responsive.html for how the card reflow and touch gestures work, and sorting.html for the keyboard and aria-sort behavior on sortable columns.