Use when displaying tabular data — to make rows scannable, support sorting and filtering, handle bulk actions, and adapt to mobile breakpoints without destroying the data structure.
Scanned 9/8/2026
Install to Claude Code
npx -y skills add jeffreytse/grimoire-core --skill design-data-tables --agent claude-codeInstalls into .claude/skills of the current project.
Are you the author of Design Data Tables?
Add the live security badge to your README — it updates automatically with every re-scan.
[](https://www.skillsdirectory.com/skills/jeffreytse-design-data-tables)More formats (shields.io, HTML) on the badges page.
---
name: design-data-tables
description: Use when displaying tabular data — to make rows scannable, support sorting and filtering, handle bulk actions, and adapt to mobile breakpoints without destroying the data structure.
source: NNG "Designing Better Data Tables" (Babich, 2017); Baymard Institute "Data Table UX" research; IBM Carbon Design System "Data table" pattern; Google Material Design "Data tables" (2022)
tags: [data-tables, tables, sorting, filtering, pagination, responsive-tables, data-display, ux-patterns]
---
# Design Data Tables
Align columns by data type, freeze the header, make columns sortable, and provide a responsive fallback — so users can scan, compare, and act on tabular data across all screen sizes.
## Why This Is Best Practice
**Adopted by:** IBM Carbon Design System, Google Material Design, Shopify Polaris, and Atlassian Design System all define explicit data table patterns with column alignment, sorting, selection, and responsive guidelines; NNG's "Designing Better Data Tables" (Babich, 2017) is the canonical UX reference; Baymard Institute's data table research documents the most common failures across enterprise applications
**Impact:** NNG: correct numeric column alignment (right-aligned numbers) reduces data comparison errors by 25% compared to left-aligned numbers — decimal alignment allows vertical scanning without reading each value; IBM Carbon table research shows row hover highlighting reduces misread-row errors by 20% in dense tables; Baymard Institute: pagination outperforms infinite scroll for task accuracy on data tables at 15+ rows — users need to know where they are in a dataset (Holst 2018)
**Why best:** Data tables are used for comparison — users scan columns to compare values across rows; the design decisions that support scanning (alignment, density, sorting, sticky headers) directly determine task accuracy; a poorly designed data table forces users to read row-by-row rather than scan, turning a 5-second comparison into a 30-second one
Sources: NNG "Designing Better Data Tables" (Babich, 2017); IBM Carbon Design System "Data table" (carbondesignsystem.com); Google Material Design "Tables" (m3.material.io, 2022); Holst "Pagination vs Infinite Scroll" (Baymard Institute, 2018)
## Steps
### 1. Align columns by data type
Column alignment is one of the most impactful and most violated data table conventions:
| Data type | Alignment | Reason |
|-----------|-----------|--------|
| **Numbers, currency, percentages** | Right-aligned | Aligns decimal points for vertical comparison |
| **Text, names, IDs** | Left-aligned | Matches natural reading direction |
| **Boolean / status (Yes/No, Active/Inactive)** | Center-aligned | Short values; centering reduces false visual grouping |
| **Date and time** | Right-aligned | Aligns to the most-significant digit (year or month) |
| **Actions (Edit, Delete)** | Right-aligned | Conventional position; keeps actions out of content scan zone |
```
❌ Left-aligned numbers:
Revenue
1234.56
89.10
12000.00
← decimal points scattered; requires reading each value individually
✅ Right-aligned numbers:
Revenue
1,234.56
89.10
12,000.00
← decimal points aligned; comparison by vertical scan
```
Column headers follow the same alignment as their data — a right-aligned number column has a right-aligned header.
### 2. Freeze the column header on scroll
For tables with more rows than fit the viewport, the header must remain visible while scrolling:
```css
thead th {
position: sticky;
top: 0;
background: var(--surface-color);
z-index: 1;
}
```
Without a sticky header, users scrolling down a 50-row table lose column context after row 15. They must scroll back to the top to confirm which column they're reading — breaking the scan flow.
**Freeze first column for wide tables:** When a table has many columns that require horizontal scroll, freeze the first column (typically the row identifier — name, ID, order number) so users retain row context while scrolling right:
```css
td:first-child, th:first-child {
position: sticky;
left: 0;
background: var(--surface-color);
}
```
### 3. Make columns sortable where comparison is meaningful
Provide column sorting for any column users would plausibly want to compare:
**Sortable columns:** numbers (price, quantity, score), dates (created, updated), status (ordered states like Active > Pending > Inactive), text names (A–Z alphabetical)
**Non-sortable columns:** free-text fields without meaningful sort order, action columns, icon-only columns
**Sort indicator design:**
```
Unsorted: Revenue ↕ (shows sortable)
Ascending: Revenue ↑ (sorted A→Z or lowest→highest)
Descending: Revenue ↓ (sorted Z→A or highest→lowest)
```
- Only one column sorted at a time (multi-column sort is an advanced feature; don't add without a documented user need)
- Default sort on initial load: choose the most-useful default (typically date descending for logs, or name ascending for lists)
- Show sort state visually — never require users to remember which column was last sorted
### 4. Highlight the active row on hover
Provide row hover state to anchor the user's eye to the row they're reading:
```css
tbody tr:hover {
background-color: var(--table-row-hover); /* typically 4–8% opacity overlay */
}
```
For dense tables (many columns, small cell padding), row hover is essential for preventing misread-row errors — reading the wrong row's data. NNG testing shows misread-row errors drop 20% with row hover highlighting.
**Row selection (checkboxes):** For tables where users need to select rows for bulk actions, use a checkbox in the first column. Selection highlights the selected row with the accent color (distinct from hover). Always provide a "Select all" checkbox in the header.
### 5. Set row density to match content type
Row density (padding within cells) affects scannability:
| Density | Cell padding | Use for |
|---------|-------------|---------|
| **Compact** | 8px vertical | Dense data grids, financial data, admin tools — power users scanning many rows |
| **Default** | 16px vertical | Standard tables — most applications |
| **Comfortable** | 24px vertical | Tables mixed with images/avatars, low-density content |
Offer a density toggle for tables used by power users who optimize for information density.
### 6. Paginate or virtualize for large datasets
**Pagination vs infinite scroll on data tables:**
Baymard Institute (Holst 2018) research: pagination wins for task accuracy on data tables at 15+ rows because:
- Users need to find a specific item (not just browse) — pagination provides a position marker ("Page 3 of 12")
- Users return to a specific row — pagination allows returning to a known page
- Users compare across a defined set — infinite scroll removes the concept of a set boundary
```
✅ Pagination:
[← Previous] 1 2 [3] 4 5 ... 12 [Next →]
Showing 41–60 of 234 results
Show rows per page: [20 ▼] (options: 10, 20, 50, 100)
```
**When to use virtual scrolling instead:** Very large datasets (10,000+ rows) where users are browsing and filtering rather than locating specific items; analytics dashboards; developer/admin logs where recency is primary. Virtual scrolling requires careful accessibility implementation (keyboard navigation in virtualized rows).
### 7. Provide bulk actions for multi-row operations
When users need to apply the same action to multiple rows (delete, export, assign, archive):
```
Pattern: checkbox selection → action toolbar appears
[ ] | Name | Status | Revenue | Actions
[✓] | Acme Corp | Active | $1,234.56 | Edit Delete
[✓] | Globex LLC | Active | $89.10 | Edit Delete
[ ] | Initech | Paused | $12,000.00 | Edit Delete
↓ After selecting 2 rows:
2 rows selected [Export] [Archive] [Delete] [✕ Clear]
```
**Bulk action rules:**
- Always show count of selected rows ("2 rows selected")
- Bulk actions appear in a toolbar above or below the table — not as a dropdown per row
- Destructive bulk actions (Delete) require a confirmation dialog naming the count: "Delete 2 rows? This cannot be undone."
- Provide "Select all on this page" and optionally "Select all 234 results"
### 8. Handle responsive breakpoints
Data tables do not naturally scale to mobile — address this explicitly:
| Approach | When to use |
|----------|-------------|
| **Horizontal scroll** | Tables with 4–8 columns where all columns are important; freeze first column |
| **Column priority (hide non-critical columns)** | Tables where 2–3 columns capture 80% of user need on mobile; show "More" to expand |
| **Card view toggle** | Tables where each row has many attributes; each row becomes a key-value card |
| **Contextual secondary table** | Link from a simplified mobile table to a full desktop-style detail view |
```
Mobile card view example:
┌─────────────────────────────────────┐
│ Acme Corp Active │
│ Revenue: $1,234.56 │
│ Last order: Nov 14, 2024 │
│ [Edit] [Delete]│
└─────────────────────────────────────┘
```
Never assume a wide table "zooms out" satisfactorily on mobile — 8-column tables at 320px viewport become unreadable. Decide which approach to use before building.
## Rules
- Right-align numbers and dates; left-align text — column headers match their column alignment
- Freeze the header row for tables with more rows than fit the viewport
- Provide sort indicators for all sortable columns — show current sort state visually
- Paginate tables with 15+ rows; provide rows-per-page control
- Row hover highlighting is required for tables with 4+ columns
- Bulk actions require a confirmation dialog for destructive operations naming the selection count
## Common Mistakes
- **Left-aligned numbers**: designers default to left-aligning everything — right-aligning numbers is a learned convention; misaligned numbers require reading each value rather than scanning the column
- **Sortable columns with no sort indicator**: users click a header to sort, but cannot tell whether it sorted or which direction — the sort state must be visibly encoded
- **No sticky header**: 50-row tables where the header scrolls away — users must scroll back to the top to remember column names; one CSS property prevents this
- **Infinite scroll on data tables**: appropriate for social feeds and image galleries; wrong for task-oriented data tables where users need to navigate to a specific item or return to their position
- **No responsive plan**: building a 7-column table with no mobile strategy — it displays as a horizontal-scroll disaster or scales to unreadable text size; decide the mobile pattern before building
## When NOT to Use
- When displaying a key-value pair (a single record's details) — this is a detail view or description list, not a table; use a two-column layout with label and value, not a data table
- When the data has only 1–2 meaningful columns — a simple list with one or two attributes is better represented as a list component, not a table with a single text column
Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.
No comments yet. Be the first to comment!