Touch Targets in Mobile Data Tables

Permalink to "Touch Targets in Mobile Data Tables"

Data tables on phones combine every touch problem: small checkboxes in narrow columns, sort arrows a few pixels wide, row action icons crammed into the last column, and rows so close together that a tap selects the wrong record. Mobile screen reader users face a different set: swipe navigation through dozens of cells per row, swipe-to-reveal actions that conflict with screen reader gestures, and tap targets with no names. WCAG 2.2 sets a minimum (24 px) and recommends more (44 px); mobile tables should aim high.

This guide belongs to responsive data tables.

Spec reference

Permalink to "Spec reference"
  • SC 2.5.8 Target Size (Minimum) (AA) — 24×24 CSS px or sufficient spacing.
  • SC 2.5.5 Target Size (Enhanced) (AAA) — 44×44 CSS px; a practical goal for touch.
  • SC 2.5.1 Pointer Gestures (A) — swipe gestures need single-pointer alternatives.
  • SC 2.5.7 Dragging Movements (AA) — drag interactions need alternatives.
  • SC 4.1.2 (A) — every target named.
Typical target sizes in a mobile table before and after Bar chart of target sizes in CSS pixels: checkbox 16 before and 44 after, sort control 18 before and 44 after, row action icon 20 before and 44 after. Typical target sizes in a mobile table before and afterCheckbox beforefails 2.5.8 without spacingSort control beforefailsRow action beforefailsCheckbox afterlabel wrapperSort control afterwhole header buttonRow action afterpadded button
Visuals can stay small; hit areas must grow.

When to use — and when not to

Permalink to "When to use — and when not to"

Apply these sizes to every table that renders on touch devices — which, given responsive design, is nearly all of them. Use pointer: coarse media queries to increase sizes on touch while keeping desktop density.

Do not rely on swipe gestures for row actions (archive, delete) without visible alternatives. The misapplication: “swipe left to delete” as the only way to delete a row, which conflicts with VoiceOver’s swipe navigation and cannot be discovered.

Swipe-only actions versus visible alternatives Comparison: swipe-only actions conflict with screen reader gestures and are undiscoverable; visible buttons or menus work for touch, screen readers and switch users. Swipe-only actions versus visible alternatives✗ Swipe to reveal actionsConflicts with VoiceOver swipe navigationUndiscoverableRequires precise gestureFails 2.5.1 without alternative✓ Visible action button or menuReachable by swiping to the buttonVisible label or icon with nameSingle tapPasses

Annotated code example

Permalink to "Annotated code example"
/* Larger targets on coarse pointers (touch) */
@media (pointer: coarse) {
  .table .cb-wrap, .table .icon-btn { min-inline-size: 44px; min-block-size: 44px; }   /* SC 2.5.5 goal */
  .table th .sort-btn { min-block-size: 44px; inline-size: 100%; text-align: start; }
  .table td, .table th { padding-block: 10px; }
}
/* Everywhere: never below 24 px (SC 2.5.8) */
.table .cb-wrap, .table .icon-btn { min-inline-size: 24px; min-block-size: 24px; display: inline-grid; place-items: center; }
<tr>
  <td><label class="cb-wrap"><input type="checkbox" aria-label="Select INV-1042"></label></td>
  <th scope="row"><a href="/invoices/1042">INV-1042</a></th>                     <!-- the link opens the row -->
  <td>1,240.00</td>
  <td><button type="button" class="icon-btn" aria-label="Actions for INV-1042">⋯</button></td>  <!-- not swipe-only -->
</tr>

Keyboard & AT behaviour

Permalink to "Keyboard & AT behaviour"
Interaction VoiceOver (iOS) TalkBack (Android)
Swipe right through a row Cells read in order Cells read in order
Double-tap the invoice link Opens record Opens record
Double-tap checkbox Toggles; “selected” Toggles; “checked”
Actions button “Actions for INV-1042, button” Same
Swipe-to-delete (if present) Conflicts with navigation; use actions rotor Conflicts; needs alternative
Mobile table interactions and accessibility Matrix of interactions — tap row to open, swipe to reveal actions, long-press menu, checkbox selection, pull to refresh — against touch users, screen reader users and the alternative to provide. Mobile table interactions and accessibilityTouch usersScreen reader usersAlternativeTap row to openEasyNeeds a linkLink in row headerSwipe to reveal actionsHiddenConflictsActions buttonLong-press menuHiddenDifferent gestureActions buttonCheckbox selectionSmall targetWorks if named44 px wrapperPull to refreshCommonGestureRefresh button
Every gesture needs a visible, single-tap alternative.

Integration context

Permalink to "Integration context"

Target size testing is covered in testing target size 2.5.8 in dense grids. Mobile screen reader behaviour is discussed in how TalkBack differs for data grid navigation and VoiceOver iOS rotor and data tables. Density tokens are in density tokens and target size in data grids.

Gotchas

Permalink to "Gotchas"

Whole-row click handlers. Making the entire row clickable with JavaScript creates a large target for sighted touch users but no accessible control; use a link in the row header (optionally stretched with CSS).

Sticky headers on mobile. Sticky headers eat screen space; keep them compact and ensure they do not obscure focused rows.

Custom actions in screen readers. iOS supports custom actions via the rotor for native apps; web apps should provide visible buttons instead.

Worked example

Permalink to "Worked example"

A field sales app showed orders in a table on phones with swipe-to-delete, 16-pixel checkboxes and a row-wide click handler. VoiceOver users could not delete orders or open them reliably, and sighted users often tapped the wrong row. The team added a link in each row header, an actions button with a menu, 44-pixel checkbox wrappers on coarse pointers, and kept swipe as an optional shortcut. Mis-taps fell and screen reader users completed the order review task for the first time.

Common mistakes

Permalink to "Common mistakes"
  • Swipe-only row actions.
  • Click handlers on rows instead of links.
  • Desktop target sizes on phones.
  • Unnamed icon buttons.

Testing checklist

Permalink to "Testing checklist"

Design system notes

Permalink to "Design system notes"

Use pointer: coarse tokens for table targets and forbid swipe-only actions in component guidelines; provide an actions button by default.

Step-by-step implementation

Permalink to "Step-by-step implementation"
  1. Audit current targets. Measure every interactive element in a row at a phone width: checkboxes, links, icon buttons, sort headers and expand toggles. Most tables fail on checkboxes and icon buttons first.
  2. Grow hit areas, not visuals. Wrap small controls in a padded label or button so the hit area reaches 44 pixels while the visual icon stays compact.
  3. Space adjacent targets. Where targets cannot grow, separate them so that 24-pixel circles centred on each do not overlap, as SC 2.5.8 allows.
  4. Replace hidden gestures. Add an actions button for anything that was swipe- or long-press-only, and keep gestures as optional shortcuts.
  5. Test on devices. Run VoiceOver on an iPhone and TalkBack on an Android phone, swiping through a row and activating every control.

Edge cases

Permalink to "Edge cases"
  • Dense mode on tablets. A density switch may shrink targets; never let the compact setting go below 24 pixels on coarse pointers.
  • Sticky action columns. A sticky last column of actions can overlap content on narrow screens; check that it does not obscure focused cells.
  • Landscape orientation. Users rotate phones to see more columns; targets must stay large in both orientations.

Testing it with a screen reader

Permalink to "Testing it with a screen reader"

On iOS, turn on VoiceOver and swipe right through one row from start to finish. Each control should be reached in order with a clear name, and double-tapping should operate it on the first try. Try to delete a row: with VoiceOver on, swipe gestures are captured by navigation, so the actions button must offer delete. On Android with TalkBack, repeat the swipe-through and use the local context menu to check for any custom actions. Then switch the screen reader off and tap each control with a finger near its edge to confirm that the enlarged hit area works and that neighbouring rows are not triggered by mistake.

FAQ

Permalink to "FAQ"
Is 24 px enough on touch?

It meets AA, but 44 px is far more usable for fingers; aim higher on touch.

Can I keep swipe gestures?

Yes, as shortcuts, with visible alternatives for everyone else.

How do I make a whole row tappable accessibly?

Put a link in the row header cell and extend its hit area with CSS (a pseudo-element covering the row), keeping one real interactive element.

Should mobile tables use cards instead?

For many tasks, yes; see the stacked card guide. Target sizes matter in both layouts.

How do screen readers navigate tables on phones?

By swiping through cells or using rotor table navigation (VoiceOver); keep rows short and well labelled.

What about tablets?

Treat them as touch devices; coarse pointer queries cover them.

Permalink to "Related"

← Back to Responsive Data Tables