⚡IntermediateAdvanced Tables
Responsive Table Patterns
Make data tables work on mobile with horizontal scroll, stacked layout, and card transforms.
Overview
HTML tables are rigid by nature they must maintain column alignment. On small screens, wide tables overflow horizontally and become unreadable or break the layout.
Three common responsive table patterns:
1. Horizontal scroll: the simplest wrap table in a scrollable container
2. Stacked layout: transform table rows into cards with CSS, using data-label attributes
3. Priority columns: hide less important columns on small screens
Each pattern trades some accessibility or information for mobile usability. The stacked approach is most mobile-friendly but requires the most CSS. Horizontal scroll preserves full data and is most accessible.
Key Points
- •Horizontal scroll wrapper: overflow-x: auto on a containing div
- •Stacked: display: block on table elements; data-label attribute for cell labels
- •Priority pattern: responsive classes hide columns at breakpoints
- •Horizontal scroll is safest for accessibility table semantics are preserved
- •Stacked layout breaks screen reader table navigation use with caution
- •caption/aria-label on the table helps users understand what they're navigating
Examples
Pattern 1: Horizontal scroll (simplest)
<style>
.table-scroll {
overflow-x: auto;
-webkit-overflow-scrolling: touch; /* smooth iOS scroll */
}
table { min-width: 600px; width: 100%; border-collapse: collapse; }
</style>
<div class="table-scroll" role="region" aria-label="Sales data scroll horizontally">
<table>
<caption>Monthly Sales Report</caption>
<thead>
<tr>
<th scope="col">Product</th>
<th scope="col">Jan</th>
<th scope="col">Feb</th>
<th scope="col">Mar</th>
<th scope="col">Total</th>
</tr>
</thead>
<tbody>
<tr>
<td>Widget A</td>
<td>120</td>
<td>145</td>
<td>132</td>
<td>397</td>
</tr>
</tbody>
</table>
</div>role="region" + aria-label on the scroll container announces the scrollable area to screen readers.
Pattern 2: Stacked card layout
<style>
@media (max-width: 640px) {
table, thead, tbody, th, td, tr { display: block; }
thead tr { position: absolute; top: -9999px; left: -9999px; } /* hide headers */
tr { border: 1px solid #ccc; margin-bottom: 12px; border-radius: 8px; }
td {
display: flex;
justify-content: space-between;
padding: 8px 12px;
border-bottom: 1px solid #eee;
}
/* Show column label before each value */
td::before {
content: attr(data-label);
font-weight: bold;
color: #374151;
}
}
</style>
<table>
<thead>
<tr>
<th scope="col">Name</th>
<th scope="col">Role</th>
<th scope="col">Salary</th>
</tr>
</thead>
<tbody>
<tr>
<td data-label="Name">Alice Smith</td>
<td data-label="Role">Developer</td>
<td data-label="Salary">$95,000</td>
</tr>
</tbody>
</table>data-label on each td mirrors the column header used by CSS ::before for mobile labels.
Pattern 3: Priority columns
<style>
@media (max-width: 480px) {
.col-secondary { display: none; }
}
</style>
<table>
<thead>
<tr>
<th scope="col">Name</th> <!-- always visible -->
<th scope="col" class="col-secondary">Email</th> <!-- hidden on mobile -->
<th scope="col" class="col-secondary">Joined</th> <!-- hidden on mobile -->
<th scope="col">Status</th> <!-- always visible -->
</tr>
</thead>
<tbody>
<tr>
<td>Alice</td>
<td class="col-secondary">alice@example.com</td>
<td class="col-secondary">2023-01-15</td>
<td>Active</td>
</tr>
</tbody>
</table>Common Mistakes
- Using the stacked pattern for complex tables with merged cells colspan/rowspan breaks
- Not adding role="region" + aria-label on the horizontal scroll wrapper screen readers can't tell it's scrollable
- Hiding column headers off-screen with visibility:hidden in stacked layout use absolute positioning trick instead
Note
For most tables, horizontal scroll is the best default. It's accessible, simple, and preserves data. Use the stacked pattern only for simple flat tables with no merged cells.
Exercises
Write HTML to solve each exercise. Use Preview to see it render in a live iframe, then mark as done.
Loading editor…
Completed: 0 / 5 exercises
Knowledge Check
Question 1 of 4