Responsive Design & Touch Gestures

TableCrafter renders a desktop data table that automatically reflows into a mobile-first card layout on small screens, with native swipe gestures, 44px touch targets, and 60fps interactions — all without any extra shortcode configuration.

Card ReflowSwipe GesturesBreakpointsTouch Targets60fps

Overview

Responsive behavior in TableCrafter is built into the frontend library — it is on by default for every table and is not toggled through a shortcode attribute. The same [tablecrafter] shortcode that renders a full HTML table on desktop will, on a phone, swap that table for a stack of touch-friendly cards. The library watches the viewport width, picks a layout for the current breakpoint, and re-renders only when the device actually crosses a breakpoint boundary (for example, when a tablet is rotated from landscape to portrait).

Because the responsive engine lives in the client library, you get the card view, swipe gestures, and accessibility refinements with a minimal shortcode:

[tablecrafter source="https://api.example.com/products.json"]
ℹ️

There is no responsive or cards attribute to set. Mobile reflow is automatic. To control which columns appear, use the standard include and exclude attributes — they apply to both the desktop table and the mobile cards.

Breakpoints

TableCrafter uses a three-tier, mobile-first breakpoint system. The active breakpoint is derived from window.innerWidth and determines which layout the table renders.

BreakpointViewport widthLayout
Mobile≤ 768pxCard view (stacked cards with expand/collapse)
Tablet769px – 900pxCompact table (tighter padding, condensed columns)
Desktop> 900pxFull data table

The classification logic is straightforward: a width of 768px or below is treated as mobile, a width up to 900px is tablet, and anything wider is desktop. There is one important refinement: a touch-only device sitting in the tablet range is still treated as "mobile" for layout purposes, so tablets get the gesture-friendly card view rather than a cramped table.

The CSS mirrors these JavaScript breakpoints with matching media queries: @media (max-width: 768px) for the mobile card styling and @media (max-width: 900px) and (min-width: 769px) for the compact portrait-tablet tier. Keeping them aligned means the layout stays consistent whether the decision was made in JS or CSS.

Mobile Card Layout

On mobile, each data row becomes a self-contained card inside a .tc-cards-container (rendered with role="list", where each card is a role="listitem"). A card is composed of:

When a card has hidden fields, it gains the .tc-card-expandable class and a toggle. Tapping the header — or swiping the card to the right — adds the .tc-card-expanded class, which reveals the hidden section and rotates the toggle. This keeps the initial card compact while still giving access to the full row.

Card labels are uppercased and de-emphasized; values wrap with word-break so long strings (URLs, emails, IDs) never force horizontal scrolling. The desktop table itself remains horizontally scrollable inside .tc-table-container with momentum scrolling on iOS for the tablet tier.

Touch Gestures

On any touch-capable device, every card is wired with a gesture handler. Touch capability is detected via ontouchstart, navigator.maxTouchPoints, or the (pointer: coarse) media query, so gestures are attached on phones and touch tablets but skipped on mouse-only desktops.

GestureAction
Swipe rightExpand or collapse the card (if it has hidden fields). Announced to screen readers as "Card expanded" / "Card collapsed".
Swipe leftOpen the floating quick-actions menu (View, Edit, Share).
TapToggle expansion (when expandable) and fire a tablecrafter:cardTap event.

A movement only counts as a swipe when it travels more than 50px horizontally, the horizontal distance exceeds the vertical distance (so vertical scrolling is never hijacked), and the whole gesture completes in under 300ms. A quick touch with no significant movement under 200ms is treated as a tap. During an active horizontal drag the card follows the finger at a damped rate and shows a directional hint — a green tint for a right swipe, a red tint for a left swipe — then springs back to its resting position on release.

Where the device supports it, the plugin adds haptic feedback through navigator.vibrate: a short pulse on a right swipe and a triple pulse when the quick-actions menu opens.

ℹ️

If you swipe right on a card that has no hidden fields (nothing to expand), TableCrafter shows a brief toast — "Swipe left for actions" — to guide the user toward the gesture that does have an effect.

Quick-Actions Menu

A left swipe opens a floating .tc-card-quick-actions menu positioned next to the card, with three buttons: View, Edit, and Share. View and Edit are extension points — by default they show a toast and fire tablecrafter:cardView / tablecrafter:cardEdit events you can hook into. Share uses the native Web Share Sheet via navigator.share when available, and falls back to copying the row's data to the clipboard with a confirmation toast.

Hooking Card Events

Card interactions dispatch bubbling CustomEvents on the table container, so you can attach your own behavior (open a modal, navigate to a detail page, log analytics) without modifying the plugin.

// Listen for taps and swipe-driven actions on a TableCrafter table
const table = document.querySelector('.tc-wrapper');

table.addEventListener('tablecrafter:cardTap', (e) => {
  // e.detail = { rowData, rowIndex, card }
  console.log('Card tapped:', e.detail.rowData);
});

table.addEventListener('tablecrafter:cardView', (e) => {
  // Triggered by the "View" quick action (left swipe)
  openDetailModal(e.detail.rowData);
});

The available card events are tablecrafter:cardTap, tablecrafter:cardView, and tablecrafter:cardEdit. Each carries the row data and index in its detail payload.

Touch Targets & Accessibility

TableCrafter follows WCAG 2.1 AA touch-target guidance. Inside @media (pointer: coarse) — i.e. any touch device — interactive controls are given a minimum size of 44px:

The library also respects user accessibility preferences. It listens for prefers-reduced-motion: reduce and prefers-contrast: high, adding .tc-reduced-motion or .tc-high-contrast to the container and updating live if the user changes their OS settings mid-session. Swipe-driven expand/collapse changes are announced through an aria-live region so screen-reader users hear the same state changes that sighted users see.

⚠️

Swipe gestures are an enhancement, not the only path. Every action they trigger is also reachable without gestures — tapping a card header expands it, and the standard controls remain keyboard-operable. Don't design a layout that depends solely on a user discovering the swipe.

Performance & 60fps

The responsive engine is built to stay smooth on phones. Drag feedback and the spring-back use direct transform changes (translate and scale), which the browser composites on the GPU rather than triggering layout. Menu and toast animations are scheduled inside requestAnimationFrame so they paint in sync with the display's refresh cycle, targeting a steady 60fps.

Crucially, resizing the window does not blindly re-render the table. The resize handler only re-renders when the viewport actually crosses the mobile threshold — switching from table to cards or back. Staying within the same breakpoint (for example, nudging a desktop window from 1100px to 1300px) costs nothing, which keeps interactions responsive even during continuous resize or rotation.

Putting It Together

A typical mobile-friendly configuration just curates the columns and lets the responsive engine do the rest. On desktop this renders a searchable table; on a phone the same rows become swipeable cards, with the columns you excluded simply absent from both views:

[tablecrafter source="https://api.example.com/inventory.json"
             include="name,sku,price,stock,supplier"
             search="true"
             per_page="20"]

The first listed column (name) becomes the card title on mobile, and the remaining fields fill the card body — with any that don't fit the breakpoint tucked into the swipe-to-expand section.

Next steps: see shortcode-reference.html for the full list of attributes that shape the table and cards, and accessibility.html for the complete WCAG 2.1 keyboard-navigation and screen-reader behavior that complements these touch gestures.